ZIP DeflateStream inside ZIP #535

Closed
opened 2026-01-29 22:13:25 +00:00 by claunia · 2 comments
Owner

Originally created by @i2um1 on GitHub (Aug 18, 2022).

Hi,

I have the following zip structure:

file.zip (method: None)
│
└───another.zip (method: Deflate)
    │
    └───7707
        │   file1.txt
        │   file2.txt
        │   ...

But the following code does not work:

using SharpCompress.Archives;
using SharpCompress.Archives.Zip;

const string filePath = @"";

await using var stream = File.OpenRead(filePath);
var archive = ZipArchive.Open(stream);
foreach (var entry in archive.Entries.Where(x => x.Key.EndsWith(".zip")))
{
    await foreach (var subEntry in GetSubEntries(entry))
    {
        Console.WriteLine(subEntry.Key);
    }
}

static async IAsyncEnumerable<ZipArchiveEntry> GetSubEntries(IArchiveEntry entry)
{
    await using var stream = entry.OpenEntryStream();
    using var archive = ZipArchive.Open(stream);

    foreach (var subEntry in archive.Entries)
    {
        yield return subEntry;
    }
}

Exception:

System.NotSupportedException: Specified method is not supported.
   at SharpCompress.Compressors.Deflate.DeflateStream.get_Length()
   at SharpCompress.IO.SourceStream.Seek(Int64 offset, SeekOrigin origin)
   at SharpCompress.IO.SourceStream.set_Position(Int64 value)
   at SharpCompress.Archives.Zip.ZipArchive.LoadVolumes(SourceStream srcStream)
   at SharpCompress.Archives.AbstractArchive`2..ctor(ArchiveType type, SourceStream srcStream)
   at SharpCompress.Archives.AbstractWritableArchive`2..ctor(ArchiveType type, SourceStream srcStream)
   at SharpCompress.Archives.Zip.ZipArchive..ctor(SourceStream srcStream)
   at SharpCompress.Archives.Zip.ZipArchive.Open(Stream stream, ReaderOptions readerOptions)
   at Program.<<Main>$>g__GetSubEntries|0_0(IArchiveEntry entry)+MoveNext() in V:\Test\Test\Program.cs:line 19
   at Program.<<Main>$>g__GetSubEntries|0_0(IArchiveEntry entry)+MoveNext() in V:\Test\Test\Program.cs:line 21
   at Program.<<Main>$>g__GetSubEntries|0_0(IArchiveEntry entry)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()
   at Program.<Main>$(String[] args) in V:\Test\Test\Program.cs:line 10
   at Program.<Main>$(String[] args) in V:\Test\Test\Program.cs:line 10
   at Program.<Main>$(String[] args) in V:\Test\Test\Program.cs:line 8
   at Program.<Main>(String[] args)

The following code has more interesting behavior without exceptions:

using SharpCompress.Common;
using SharpCompress.Readers;

const string filePath = @"";

await using var stream = File.OpenRead(filePath);

var reader = ReaderFactory.Open(stream);
while (reader.MoveToNextEntry())
{
    if (reader.Entry.Key.EndsWith(".zip"))
    {
        await foreach (var subEntry in GetSubEntries(reader))
        {
            Console.WriteLine(subEntry.Key);
        }
    }
}

static async IAsyncEnumerable<IEntry> GetSubEntries(IReader reader)
{
    await using var stream = reader.OpenEntryStream();
    var subReader = ReaderFactory.Open(stream);
    
    while (subReader.MoveToNextEntry())
    {
        yield return subReader.Entry;
    }
}

Console Output:

7707/

I know it's stupid to have a zip file inside a zip file. But is it possible somehow to make it work?

Originally created by @i2um1 on GitHub (Aug 18, 2022). Hi, I have the following zip structure: ``` file.zip (method: None) │ └───another.zip (method: Deflate) │ └───7707 │ file1.txt │ file2.txt │ ... ``` But the following code does not work: ```cs using SharpCompress.Archives; using SharpCompress.Archives.Zip; const string filePath = @""; await using var stream = File.OpenRead(filePath); var archive = ZipArchive.Open(stream); foreach (var entry in archive.Entries.Where(x => x.Key.EndsWith(".zip"))) { await foreach (var subEntry in GetSubEntries(entry)) { Console.WriteLine(subEntry.Key); } } static async IAsyncEnumerable<ZipArchiveEntry> GetSubEntries(IArchiveEntry entry) { await using var stream = entry.OpenEntryStream(); using var archive = ZipArchive.Open(stream); foreach (var subEntry in archive.Entries) { yield return subEntry; } } ``` Exception: ``` System.NotSupportedException: Specified method is not supported. at SharpCompress.Compressors.Deflate.DeflateStream.get_Length() at SharpCompress.IO.SourceStream.Seek(Int64 offset, SeekOrigin origin) at SharpCompress.IO.SourceStream.set_Position(Int64 value) at SharpCompress.Archives.Zip.ZipArchive.LoadVolumes(SourceStream srcStream) at SharpCompress.Archives.AbstractArchive`2..ctor(ArchiveType type, SourceStream srcStream) at SharpCompress.Archives.AbstractWritableArchive`2..ctor(ArchiveType type, SourceStream srcStream) at SharpCompress.Archives.Zip.ZipArchive..ctor(SourceStream srcStream) at SharpCompress.Archives.Zip.ZipArchive.Open(Stream stream, ReaderOptions readerOptions) at Program.<<Main>$>g__GetSubEntries|0_0(IArchiveEntry entry)+MoveNext() in V:\Test\Test\Program.cs:line 19 at Program.<<Main>$>g__GetSubEntries|0_0(IArchiveEntry entry)+MoveNext() in V:\Test\Test\Program.cs:line 21 at Program.<<Main>$>g__GetSubEntries|0_0(IArchiveEntry entry)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult() at Program.<Main>$(String[] args) in V:\Test\Test\Program.cs:line 10 at Program.<Main>$(String[] args) in V:\Test\Test\Program.cs:line 10 at Program.<Main>$(String[] args) in V:\Test\Test\Program.cs:line 8 at Program.<Main>(String[] args) ``` The following code has more interesting behavior without exceptions: ```cs using SharpCompress.Common; using SharpCompress.Readers; const string filePath = @""; await using var stream = File.OpenRead(filePath); var reader = ReaderFactory.Open(stream); while (reader.MoveToNextEntry()) { if (reader.Entry.Key.EndsWith(".zip")) { await foreach (var subEntry in GetSubEntries(reader)) { Console.WriteLine(subEntry.Key); } } } static async IAsyncEnumerable<IEntry> GetSubEntries(IReader reader) { await using var stream = reader.OpenEntryStream(); var subReader = ReaderFactory.Open(stream); while (subReader.MoveToNextEntry()) { yield return subReader.Entry; } } ``` Console Output: ``` 7707/ ``` I know it's stupid to have a zip file inside a zip file. But is it possible somehow to make it work?
Author
Owner

@Erior commented on GitHub (Aug 25, 2022):

The output from a deflated stream is not seekable, you can not use the ZipArchive call directly, you would need to copy to temporary file or MemoryStream to make it seekable.
If the internal zip was in "stored" mode, you would end up with an error regarding ReadOnlySubStream instead of deflate stream, same solution would apply.

ReaderFactory does not use the CentralArchive information at the end of the archive and tries to read from the start.

Archive: file.zip
Zip file size: 5600 bytes, number of entries: 1
-rw-r--r-- 3.0 unx 5428 bx stor 22-Aug-25 21:57 another.zip
1 file, 5428 bytes uncompressed, 5428 bytes compressed: 0.0%

Archive: another.zip
Zip file size: 5428 bytes, number of entries: 4
drwxr-xr-x 3.0 unx 0 bx stor 22-Aug-25 21:57 7707/
-rw-r--r-- 3.0 unx 4096 bx defN 22-Aug-25 21:57 7707/file1.txt
-rw-r--r-- 3.0 unx 4096 bx defN 22-Aug-25 21:57 7707/file2.txt
-rw-r--r-- 3.0 unx 4096 bx defN 22-Aug-25 21:57 7707/file3.txt
4 files, 12288 bytes uncompressed, 4800 bytes compressed: 60.9%

Output from code with ReaderFactory

7707/
7707/file1.txt
7707/file2.txt
7707/file3.txt

This works then because we do not try to read the end of the file and then jump back to the start on a stream that does not handle Seek or setting position.

@Erior commented on GitHub (Aug 25, 2022): The output from a deflated stream is not seekable, you can not use the ZipArchive call directly, you would need to copy to temporary file or MemoryStream to make it seekable. If the internal zip was in "stored" mode, you would end up with an error regarding ReadOnlySubStream instead of deflate stream, same solution would apply. ReaderFactory does not use the CentralArchive information at the end of the archive and tries to read from the start. Archive: file.zip Zip file size: 5600 bytes, number of entries: 1 -rw-r--r-- 3.0 unx 5428 bx stor 22-Aug-25 21:57 another.zip 1 file, 5428 bytes uncompressed, 5428 bytes compressed: 0.0% Archive: another.zip Zip file size: 5428 bytes, number of entries: 4 drwxr-xr-x 3.0 unx 0 bx stor 22-Aug-25 21:57 7707/ -rw-r--r-- 3.0 unx 4096 bx defN 22-Aug-25 21:57 7707/file1.txt -rw-r--r-- 3.0 unx 4096 bx defN 22-Aug-25 21:57 7707/file2.txt -rw-r--r-- 3.0 unx 4096 bx defN 22-Aug-25 21:57 7707/file3.txt 4 files, 12288 bytes uncompressed, 4800 bytes compressed: 60.9% Output from code with ReaderFactory 7707/ 7707/file1.txt 7707/file2.txt 7707/file3.txt This works then because we do not try to read the end of the file and then jump back to the start on a stream that does not handle Seek or setting position.
Author
Owner

@i2um1 commented on GitHub (Aug 26, 2022):

Oh, I see, thank you for the description.

@i2um1 commented on GitHub (Aug 26, 2022): Oh, I see, thank you for the description.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/sharpcompress#535