Tom*_*ter 10 .net c# compression wpf gzipstream
我正在尝试序列化和压缩WPF FlowDocument,然后反向 - 解压缩字节数组并反序列化以重新创建FlowDocument - 使用.NET GZipStream类.我正在关注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);
Run Code Online (Sandbox Code Playgroud)
但是XamlReader.Load,由于调试输出告诉未压缩的流的长度为零,因此在线路上出现异常是正常的.
Compress
uncompressed.Length: 123
compressed.Length: 202
Decompress
compressed.Length: 202
uncompressed.Length: 0
Run Code Online (Sandbox Code Playgroud)
为什么最终uncompressed流不包含原始的123字节?
(请忽略"压缩"字节数组大于"未压缩"字节数组的事实 - 我通常会使用更大的流文档)
Joã*_*elo 12
您需要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();
}
Run Code Online (Sandbox Code Playgroud)
这可以工作,你甚至可以删除它using,MemoryStream因为它将被处理,GZipStream除非你使用构造函数重载,允许你指定底层流应该保持打开.这意味着使用该代码调用ToArray已处理的流,但这是允许的,因为字节仍然可用,这使得处理内存流有点奇怪,但如果你不这样做,FXCop会惹恼你.
若昂的回答起到了作用。我复制了下面的完整工作示例。我在输出中添加了一行compressedData.Length。有趣的是,它输出 218 字节,而compressedStream.Length仅输出 202 字节。如果您在读取字节数组之前不关闭 GZipStream,则为compressedData.Length202。我不确定为什么关闭 GZipStream 会给您带来额外的 16 个字节。
var flowDocumentIn = new FlowDocument();
flowDocumentIn.Blocks.Add(new Paragraph(new Run("Hello")));
Debug.WriteLine("Compress");
byte[] compressedData;
using (var uncompressedStream = new MemoryStream())
{
XamlWriter.Save(flowDocumentIn, uncompressedStream);
uncompressedStream.Position = 0;
using (var compressedStream = new MemoryStream())
{
using (var gZipCompressor = new GZipStream(compressedStream, CompressionMode.Compress))
{
Debug.WriteLine(" uncompressedStream.Length: " + uncompressedStream.Length);
uncompressedStream.CopyTo(gZipCompressor);
Debug.WriteLine(" compressedStream.Length: " + compressedStream.Length);
}
compressedData = compressedStream.ToArray();
}
}
Debug.WriteLine(" compressedData.Length: " + compressedData.Length);
Debug.WriteLine("Decompress");
FlowDocument flowDocumentOut;
using (var compressedStream = new MemoryStream(compressedData))
using (var uncompressedStream = new MemoryStream())
{
using (var gZipDecompressor = new GZipStream(compressedStream, CompressionMode.Decompress))
{
Debug.WriteLine(" compressedStream.Length: " + compressedStream.Length);
gZipDecompressor.CopyTo(uncompressedStream);
Debug.WriteLine(" uncompressedStream.Length: " + uncompressedStream.Length);
}
uncompressedStream.Position = 0;
flowDocumentOut = (FlowDocument)XamlReader.Load(uncompressedStream);
}
Run Code Online (Sandbox Code Playgroud)
调试输出:
Compress
uncompressedStream.Length: 123
compressedStream.Length: 202
compressedData.Length: 218
Decompress
compressedStream.Length: 218
uncompressedStream.Length: 123
Run Code Online (Sandbox Code Playgroud)
uncompressedStream.Position = 0;另请注意调用 to 之前的附加内容XamlReader.Load。
| 归档时间: |
|
| 查看次数: |
5370 次 |
| 最近记录: |