Search code examples
c#gzipbinaryreader

how to get position and length of unzipped gzipstream in c#?


i'm trying to read .gz files using binary reader by first unzipping with gzipstream, and then creating a new binary reader with the gzipstream. however, when i try to use the BaseStream.Position and BaseStream.Length of BinaryReader (to know when i'm at the end of my file), i get a NotSupportedException, checking the doc for these fields in GZipStream Class shows:

Length
This property is not supported and always throws a NotSupportedException.(Overrides Stream.Length.)

Position
This property is not supported and always throws a NotSupportedException.(Overrides Stream.Position.)

so my question is how can i know when i'm at the end of my file when reading a decompressed GZipStream using BinaryReader? thanks

here is my code:

Stream stream = new MemoryStream(textAsset.bytes);
GZipStream zippedStream = new GZipStream(stream, CompressionMode.Decompress);
using (BinaryReader reader = new BinaryReader(zippedStream))
    while(reader.BaseStream.Position != reader.BaseStream.Length)
    {
        //do stuff with BinaryReader
    }

the above throws: NotSupportedException: Operation is not supported. System.IO.Compression.DeflateStream.get_Position()

due to the BaseStream.Position call in the while()


Solution

  • You can copy your zippedStream to MemoryStream instance, that can be read fully using ToArray function. That is the easiest solution I can think of.

    Stream stream = new MemoryStream(textAsset.bytes);
    byte[] result;
    using (GZipStream zippedStream = new GZipStream(stream, CompressionMode.Decompress))
    {
        using (MemoryStream reader = new MemoryStream())
        {
            zippedStream.CopyTo(reader);
            result = reader.ToArray();
        }
    }
    

    Alternatively if you want to read stream in chunks

    using (GZipStream zippedStream = new GZipStream(stream, CompressionMode.Decompress))
    {
        byte[] buffer = new byte[16 * 1024];
        int read;
        while ((read = zippedStream.Read(buffer, 0, buffer.Length)) > 0)
        {
            // do work
        }
    }