【问题标题】:GZipStream does gzipping but ungzipping file end up with "Unexpected end of data"GZipStream 进行 gzip 压缩,但解压缩文件以“意外的数据结尾”结尾
【发布时间】:2023-03-08 20:16:01
【问题描述】:

有谁知道为什么我在解压缩 gzip 文件时收到“意外的数据结束”错误消息?

为了验证字节数据没有损坏,我使用FooTest4.csv 写入文件并能够成功打开文件。

'FooTest3.csv.gzand 'FooTest2.csv.gz 在解压缩时都遇到了“意外的数据结尾”。

    public static List<byte> CompressFile(List<byte> parmRawBytes)
    {
        //Initialize variables...
        List<byte> returnModifiedBytes = null;

        File.WriteAllBytes(@"X:\FooTest4.csv", parmRawBytes.ToArray());

        using (var memoryStream = new MemoryStream())
        {
            using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress, false))
            {
                gzipStream.Write(parmRawBytes.ToArray(), 0, parmRawBytes.ToArray().Length);
                gzipStream.Flush();
                File.WriteAllBytes(@"X:\FooTest3.csv.gz", memoryStream.ToArray());
                returnModifiedBytes = memoryStream.ToArray().ToList();
            }
        }

        File.WriteAllBytes(@"X:\FooTest2.csv.gz", returnModifiedBytes.ToArray());

        return returnModifiedBytes;
    }

【问题讨论】:

  • 您过早地调用memoryStream.ToArray()GZipStream.Dispose 将内容写入其底层流。删除对gzipStream.Flush 的调用(没有实际意义),然后从内部using 块下拉出对memoryStream.ToArray() 的调用。
  • 拨打memoryStream.ToArray(),这是什么意思?
  • 将它放在外部 using 块内,但在内部:using (var memoryStream = ...) { using (var gzipStream = ...) { gzipStream.Write(...); } memoryStream.ToArray(); } 之外。
  • 就是这样!现在可以了。我很惊讶它必须在外面才能工作,这意味着必须先关闭 gzipstream。
  • 没什么好惊讶的。 GZip 压缩方法不是附加的,它必须准确知道所有传入数据何时结束才能发出压缩数据。这就是为什么FlushGZipStream 没有影响。您调用 Flush 并不意味着您以后不会插入更多数据 - 要添加的每个新字节都可能会更改整个压缩数据块。

标签: c# gzipstream


【解决方案1】:

GZipStream 需要关闭,以便它可以将一些终止数据写入缓冲区的末尾以完成 gzip 编码。

byte[] inputBytes = ...;
using (var compressedStream = new MemoryStream())
{
    using (var compressor = new GZipStream(compressedStream, CompressionMode.Compress))
    {
        compressor.Write(inputBytes, 0, inputBytes.Length);
    }

    // get bytes after the gzip stream is closed 
    File.WriteAllBytes(pathToFile, compressedStream.ToArray());
}

【讨论】:

  • 给你积分,这样旧帖子就可以关闭了。我不记得一年前我做了什么让它工作。 :-)
【解决方案2】:

您可以同时进行压缩和写入,而不是加载字节、压缩和保存它们。另外我不知道您为什么使用List&lt;Byte&gt; 而不是byte[],也许就是这样。

void CompressFile(string inputPath, string outputPath)
{
   Stream readStream = new FileStream(inputPath, Filemode.Open);
   Stream writeStream = new FileStream(outputPath, FileMode.Create);
   Stream compressionStream = new GZipStream(writeStream. CompressionMode.Compress);
   byte[] data = new byte[readStream.Length];
   readStream.Read(data, 0, data.Length);
   compressionStream.Write(data, 0, data.Length);
   readStream.Close();
   writeStream.Close();    
}

byte[] CompressFile(string inputPath)
{
  byte[] data = File.ReadAllBytes(inputPath);
  MemoryStream memStream = new MemoryStream(data);
  var gzipStream = new GZipStream(memStream, CompressionMode.Compress);
  gzipStream.Write(data, 0, data.Length);
  gzipStream.Close();
  return gzipStream.ToArray();
}

PS:我是在文本编辑器中编写代码的,所以可能会有错误。你还说错误是在“解压缩”上,为什么不给我们解压缩码?

【讨论】:

  • 不想写磁盘,只写内存。
  • 但是在您的代码上,您正在写入磁盘。我会编辑答案。
  • 调试用的那部分。返回值返回字节数据。哦,好吧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多