sharpcompress
sharpcompress copied to clipboard
System.NotSupportedException on reader.MoveToNextEntry()
Unzipping a 7z file fails with System.NotSupportedException
on the last MoveToNextEntry()
call.
On inspecting the results in file explorer, I can see it's successfully finished extraction, so I guess MoveToNextEntry()
is hitting an error of some kind instead of discovering that it's at the end of the archive?.
If it helps, the 7z archive I'm working with can be downloaded here: https://www.nexusmods.com/oblivion/mods/5296?tab=files&file_id=1000024710
Stack Trace:
at SharpCompress.Compressors.LZMA.DecoderRegistry.CreateDecoderStream(CMethodId id, Stream[] inStreams, Byte[] info, IPasswordProvider pass, Int64 limit)
at SharpCompress.Compressors.LZMA.DecoderStreamHelper.CreateDecoderStream(Stream inStream, Int64 startPos, Int64[] packSizes, CFolder folderInfo, IPasswordProvider pass)
at SharpCompress.Common.SevenZip.ArchiveDatabase.GetFolderStream(Stream stream, CFolder folder, IPasswordProvider pw)
at SharpCompress.Archives.SevenZip.SevenZipArchive.SevenZipReader.<GetEntries>d__7.MoveNext()
at SharpCompress.Readers.AbstractReader`2.MoveToNextEntry()
at U_Mod.Models.ZipFileWorker.UncompressZip(String inFile, String outDirectory) in C:\Users\saitk\Programming\WPF\U-Mod\U-Mod\Models\ZipFileWorker.cs:line 181
Thanks :)
If you're extracting using the ReaderFactory
, it seems that 7z support is missing there. As an workaround, you can try open it manually with SevenZipArchive.Open()
. ~~But the progress seems not to work using this way~~ and self-writing a wrapper doesn't work because the RewindableStream
class is mostly declared as internal.
You can use the event when calling ExtractAllEntries()
on the archive like this:
using (var archive = SevenZipArchive.Open(archivePath)) {
using (var reader = archive.ExtractAllEntries()) {
reader.EntryExtractionProgress += Reader_EntryExtractionProgress;
reader.WriteAllToDirectory(targetDir, options);
}
}
private void Reader_EntryExtractionProgress(object sender, ReaderExtractionEventArgs<IEntry> e) {
log.Info($"{e.Item.Key}: {e.ReaderProgress.PercentageRead} % read, {e.ReaderProgress.PercentageReadExact} % extracted");
}
Extracting other formats with the auto-detection of the ReaderFactory
class can still be used. Until this is fixed, you just need to check yourself first if the archive is a 7z archive and extract it manually, otherwise use ReaderFactory
like this:
if (SevenZipArchive.IsSevenZipFile(archivePath)) {
ExtractSevenZip(archivePath, targetDir, options);
} else {
ExtractWithAutoDetectFactory(archivePath, targetDir, options);
}
It's a bit more manual work, but it works and both allow to show the correct progress (usefull on larger files and/or slower machines/disks).
Thanks for helping @DMW007
Readers aren't used with 7Zip because 7Zip requires random access on the stream. Reader is built for non-seekable streams while Archive is built for seekable streams.
Thank you @adamhathcock for the explanation. I'd suggest to document this in the usage guide, so it's clear that the auto extractor cannot work with 7zip archives.
ArchiveFactory does work with 7Zip though