3
votes

How can we create a simple function to take the compressed content from an array of byte (compressed with Deflate method, ANSI encoded) and express it in a string?

I go with this one :

public string UnzipString3(byte[] byteArrayCompressedContent)
    {
        int compressedSize = byteArrayCompressedContent.Length;
        try
        {
            using (MemoryStream inputMemoryStream = new MemoryStream(byteArrayCompressedContent))
            {
                //I need to consume the first 2 bytes to be able read the stream
                //If I consume 0 or 4, I can't exploit it                        
                inputMemoryStream.Seek(2, SeekOrigin.Begin);
                using (DeflateStream deflateStream = new DeflateStream(inputMemoryStream, System.IO.Compression.CompressionMode.Decompress))
                {
                    //deflateStream.BaseStream.Position = 0;
                    using (StreamReader reader = new StreamReader(deflateStream, System.Text.Encoding.UTF8))
                    {
                        string uncompressedContent = reader.ReadToEnd();
                        reader.Close();
                        return uncompressedContent;
                    }
                }
            }
        }
        catch (Exception e)
        {
            return "";
        }
    }

I can see read the compressed data of inputMemoryStream if I want but the uncompressedContent given by StreamReader.ReadToEnd() always return an empty string. According to MSDN (https://msdn.microsoft.com/en-us/library/system.io.streamreader.readtoend(v=vs.110).aspx), it is supposed to happen when it is read and the position is already at the end of the "Stream" (I get confused with which stream), but a StreamReader hasn't a position and I can't change the position of the DeflateStream, because it's a stream without a position and the length, etc.

Putting the compressStream position to 0 before to copy leads to a Block length does not match with its complement" error in any case.

EDIT:

When I use the solution of RaTruong :

public static string UnzipString3(byte[] byteArrayCompressedContent)
{
    using (var outputStream = new MemoryStream())
    {
        using (var compressStream = new MemoryStream(byteArrayCompressedContent))
        {
            using (var deflateStream = new DeflateStream(compressStream, CompressionMode.Decompress))
            {
                deflateStream.CopyTo(outputStream);
            }
        }
        return Encoding.UTF8.GetString(outputStream.ToArray());
    }
}

It leads to the dilemma I always had: either I do like this and the DeflateStream.CopyTo function returns a "Block length does not match with its complement" error, or I consume then two first bytes and it actually does not bring any error but still copy nothing and then returns an empty string...

If I try to decompress a FileStream of a File instead of its array of bytes, the same situation happens. I use the decompress function given in MSDN (https://msdn.microsoft.com/en-us/library/system.io.compression.deflatestream(v=vs.110).aspx) :

public string ExtractContent()
    {
        try
        {
            FileInfo fileInfo = new FileInfo("22CC0001.23U");
            // Get the stream of the source file.
            using (FileStream inFile = fileInfo.OpenRead())
            {
                // Get original file extension, for example
                // "doc" from report.doc.gz.
                string curFile = fileInfo.FullName;
                string origName = curFile.Remove(curFile.Length -
                        fileInfo.Extension.Length);
                //Create the decompressed file.
                using (FileStream outFile = File.Create(origName))
                {
                    using (DeflateStream decompressDeflateStream = new DeflateStream(inFile,
                            CompressionMode.Decompress))
                    {
                        // Copy the decompression stream 
                        // into the output file.
                        decompressDeflateStream.CopyTo(outFile);

                        Console.WriteLine("Decompressed: {0}", fileInfo.Name);
                    }
                }
            }
        }
        catch (Exception e)
        {
            return "errorelole";
        }
        return "";
    }

Same "Block length does not match with its complement" error...

One thing is that the extension of my file is not a ".zip" added at the end of a file, but another extension (.23U in that case). When I create a new file having the same extension (.23U instead of no extension in that case), the same problem occurs.

1
After putting data into a MemoryStream the point is at last location. So before reading set position to inputMemoryStream.Postition = 0;jdweng
You'll have to find out more about the file format and the data you should expect to retrieve. Do consider that an empty string is entirely normal. Google never heard of it, talk to the programmer that wrote the software that generated the file.Hans Passant

1 Answers

1
votes

Your unzip method should be something like below. Not sure where you got the idea of consuming the first 2 bytes before you can read the stream.

    public static string UnzipString3(byte[] byteArrayCompressedContent)
    {
        using (var outputStream = new MemoryStream())
        {
            using (var compressStream = new MemoryStream(byteArrayCompressedContent))
            {
                using (var deflateStream = new DeflateStream(compressStream, CompressionMode.Decompress))
                {
                    deflateStream.CopyTo(outputStream);
                }
            }

            return Encoding.UTF8.GetString(outputStream.ToArray());
        }
    }