c# - .NET GZipStream 解压缩生成空流

标签 c# .net wpf compression gzipstream

我正在尝试序列化和压缩 WPF FlowDocument ,然后执行相反的操作 - 解压缩字节数组并反序列化以重新创建 FlowDocument - 使用 .NET GZipStream类(class)。我正在按照 MSDN 上描述的示例进行操作,并且我有以下测试程序:

var flowDocumentIn = new FlowDocument();
flowDocumentIn.Blocks.Add(new Paragraph(new Run("Hello")));
Debug.WriteLine("Compress");
byte[] compressedData;
using (var uncompressed = new MemoryStream())
{
    XamlWriter.Save(flowDocumentIn, uncompressed);
    uncompressed.Position = 0;
    using (var compressed = new MemoryStream())
    using (var compressor = new GZipStream(compressed, CompressionMode.Compress))
    {
        Debug.WriteLine(" uncompressed.Length: " + uncompressed.Length);
        uncompressed.CopyTo(compressor);
        Debug.WriteLine(" compressed.Length: " + compressed.Length);
        compressedData = compressed.ToArray();
    }
}

Debug.WriteLine("Decompress");
FlowDocument flowDocumentOut;
using (var compressed = new MemoryStream(compressedData))
using (var uncompressed = new MemoryStream())
using (var decompressor = new GZipStream(compressed, CompressionMode.Decompress))
{
    Debug.WriteLine(" compressed.Length: " + compressed.Length);
    decompressor.CopyTo(uncompressed);
    Debug.WriteLine(" uncompressed.Length: " + uncompressed.Length);
    flowDocumentOut = (FlowDocument) XamlReader.Load(uncompressed);
}

Assert.AreEqual(flowDocumentIn, flowDocumentOut);

但是我在 XamlReader.Load 行遇到异常,这是正常的,因为调试输出表明未压缩流的长度为零。

Compress
 uncompressed.Length: 123
 compressed.Length: 202
Decompress
 compressed.Length: 202
 uncompressed.Length: 0

为什么最终的未压缩流不包含原始的 123 个字节?

(请忽略“压缩”字节数组比“未压缩”字节数组大的事实——我通常会处理更大的流文档)

最佳答案

在从内存流中获取压缩字节之前,您需要关闭GZipStream。在这种情况下,关闭由因使用而调用的 Dispose 处理。

using (var compressed = new MemoryStream())
{
    using (var compressor = new GZipStream(compressed, CompressionMode.Compress))
    {
        uncompressed.CopyTo(compressor);
    }
    // Get the compressed bytes only after closing the GZipStream
    compressedBytes = compressed.ToArray();
}

这行得通,您甚至可以删除 MemoryStreamusing,因为它将由 GZipStream 处理,除非您使用构造函数重载这允许您指定底层流应该保持打开状态。这意味着您正在使用该代码在已处置的流上调用 ToArray 但这是允许的,因为字节仍然可用,这使得处置内存流有点奇怪,但如果您不这样做,FXCop 会惹恼您.

关于c# - .NET GZipStream 解压缩生成空流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11915612/

相关文章:

c# - EF Core 3.1 查询有时超快但有时很慢

c# - 如何在不使用 TaskCreationOptions.AttachedToParent 的情况下等待所有任务(创建的任务和子任务)

c# - JToken 序列化为字符串 json.net

c# - 优化 Parallel.For 的性能

c# - invalidate 方法有什么作用?

c# - 线程之间的线程通信

c# - 创建位图时的相对路径

c# - 将多个网址重定向到单个网址

c# - 如何在 WPF(MVVM/ Entity Framework )中更新表单时显示从数据库到 TextBlock 的外键数据值?

c# - 在 MVVM 中,如果 UI 不需要更新,模型中的属性是否需要属性更改事件?