Запись в поток сжатия не поддерживается. Использование System.IO.GZipStream - PullRequest
7 голосов
/ 30 августа 2009

Я получаю исключение при попытке распаковать файл (.gz) с помощью класса GZipStream, который включен в .NET Framework. Я использую документацию MSDN. Это исключение:

Запись в поток сжатия не поддерживается.

Вот источник приложения:

 try
 {
     var infile = new FileStream(@"C:\TarDecomp\TarDecomp\TarDecomp\bin\Debug\nick_blah-2008.tar.gz", FileMode.Open, FileAccess.Read, FileShare.Read);
     byte[] buffer = new byte[infile.Length];
     // Read the file to ensure it is readable.
     int count = infile.Read(buffer, 0, buffer.Length);
     if (count != buffer.Length)
     {
         infile.Close();
         Console.WriteLine("Test Failed: Unable to read data from file");
         return;
     }
     infile.Close();
     MemoryStream ms = new MemoryStream();
     // Use the newly created memory stream for the compressed data.
     GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Decompress, true);
     Console.WriteLine("Decompression");
     compressedzipStream.Write(buffer, 0, buffer.Length); //<<Throws error here
     // Close the stream.
     compressedzipStream.Close();
     Console.WriteLine("Original size: {0}, Compressed size: {1}", buffer.Length, ms.Length);
} catch {...}

Исключение выдается при сжатии ZipStream.write ().

Есть идеи? Что говорит мне это исключение?

Ответы [ 3 ]

16 голосов
/ 30 августа 2009

Он говорит вам, что вы должны позвонить Read вместо Write, поскольку это декомпрессия! Также поток памяти должен быть построен с данными, или, скорее, вы должны передать поток файлов непосредственно в конструктор GZipStream.

Пример того, как это должно было быть сделано (не пытался его скомпилировать):

Stream inFile = new FileStream(@"C:\TarDecomp\TarDecomp\TarDecomp\bin\Debug\nick_blah-2008.tar.gz", FileMode.Open, FileAccess.Read, FileShare.Read);
Stream decodedStream = new MemoryStream();
byte[] buffer = new byte[4096];

using (Stream inGzipStream = new GZipStream(inFile, CompressionMode.Decompress))
{
    int bytesRead;
    while ((bytesRead = inGzipStream.Read(buffer, 0, buffer.Length)) > 0)
        decodedStream.Write(buffer, 0, bytesRead);
}

// Now decodedStream contains the decoded data
9 голосов
/ 30 августа 2009

Код сжатия не работает как шифрование - вы не можете распаковать из одного потока в другой, записав сжатые данные. Вы должны предоставить поток, который уже содержит сжатые данные, и позволить GZipStream читать из него. Как то так:

using (Stream file = File.OpenRead(filename))
using (Stream gzip = new GZipStream(file, CompressionMode.Decompress))
using (Stream memoryStream = new MemoryStream())
{
   CopyStream(gzip, memoryStream);
   return memoryStream.ToArray();
}

CopyStream - это простой служебный метод для чтения из одного потока и копирования всех данных в другой. Как то так:

static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[8192];
    int bytesRead;
    while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write(buffer, 0, bytesRead);
    }
}
1 голос
/ 30 августа 2009

Поначалу работа потоков сжатия может вызывать недоумение.

Чтение требует сжатых данных, а запись занимает несжатых данных. В общем, поток гарантирует, что вы всегда «видите» несжатые данные.

Правильный способ добиться того, что вы пытаетесь сделать, - это читать, используя GZipStream, а затем писать, используя также GZipStream.

...