写入压缩流不受支持。使用System.IO.GZipStream。

8

我使用.NET框架中包含的GZipStream类尝试解压缩(.gz)文件时遇到了异常。我使用的是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 {...}

异常出现在compressedZipStream.write()。

有什么想法吗?这个异常告诉我什么?

3个回答

16

它告诉你应该调用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

压缩代码与加密不同 - 你不能通过写入压缩数据来从一个流中解压到另一个流中。你必须提供一个包含已经压缩数据的流,并让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

压缩流的工作原理一开始可能会让人感到困惑。

读取操作需要处理 压缩 数据,而写入操作则需要处理 未压缩 数据。总之,流确保您始终只能“看到”未压缩的数据。

实现您所需的功能的正确方法是使用 GZipStream 进行读取,然后再使用 GZipStream 进行写入。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接