简体   繁体   English

MemoryStream CopyTo只是部分写入

[英]MemoryStream CopyTo only partially writing

I'm about to lose my freaking mind. 我即将失去我的怪异头脑。 I've been trying to get GzipStream to compress a string for the past hour, but for whatever reason, it refuses to write the entire byte array to the memory stream. 我一直试图让GzipStream在过去一小时内压缩字符串,但无论出于何种原因,它都拒绝将整个字节数组写入内存流。 At first I thought it had something to do with the using statements, but even after removing them it didn't seem to make a difference. 起初我认为它与using语句有关,但即使在删除它们之后它似乎也没有什么区别。

Initial config: 初始配置:

var str = "Here is a relatively simple string to compress";
byte[] compressedBytes;
string returnedData;

var bytes = Encoding.UTF8.GetBytes(str);

Works correctly (writes 64 length byte array): 工作正常(写64长度字节数组):

using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream()) {
   using (var gs = new GZipStream(mso, CompressionMode.Compress)) {
       msi.CopyTo(gs);
   }

   compressedBytes = mso.ToArray();
}

Fails (writes 10 length byte array): 失败(写入10个长度字节数组):

using(var mso = new MemoryStream())
using(var msi = new MemoryStream(bytes))
using(var zip = new GZipStream(mso, CompressionMode.Compress))
{
    msi.CopyTo(zip);
    compressedBytes = mso.ToArray();
}

Also fails (writes 10 length byte array): 也失败(写入10个长度字节数组):

var mso = new MemoryStream();
var msi = new MemoryStream(bytes);
var zip = new GZipStream(mso, CompressionMode.Compress);

msi.CopyTo(zip);
compressedBytes = mso.ToArray();

Can somebody explain why the first one works but in the other two I'm getting these incomplete arrays? 有人可以解释为什么第一个可以工作,但在另外两个我得到这些不完整的数组? Is something getting disposed out from under me? 是什么东西从我身下消失了? For that matter, is there a way for me to avoid using two memorystreams? 就此而言,我有办法避免使用两个内存流吗?

Thanks, Zoombini 谢谢,Zoombini

System.IO.Compression.GZipStream has to be closed (disposed) before you can use the underlying stream, because 必须先关闭(处置) System.IO.Compression.GZipStream才能使用基础流,因为

  1. It works block oriented 它以块为导向
  2. It has to write the footer, including the checksum (see the file format description on Wikipedia ) 它必须写入页脚,包括校验和(请参阅Wikipedia上的文件格式说明

You're trying to get the the compressed data before GZipStream is closed. 您正在尝试在GZipStream关闭之前获取压缩数据。 This doesn't return the full data, as you've seen. 正如您所见,这不会返回完整数据。 The reason the first one works is because you're calling compressedBytes = mso.ToArray(); 第一个工作的原因是因为你正在调用compressedBytes = mso.ToArray(); after GZipStream has been disposed. GZipStream被处置之后。 So, untested but in theory, you should be able to modify your second code slightly like this to get it to work. 所以,未经测试但理论上,您应该能够稍微修改您的第二个代码,以使其工作。

using(var mso = new MemoryStream())
{
   using(var msi = new MemoryStream(bytes))
   using(var zip = new GZipStream(mso, CompressionMode.Compress))
   {
       msi.CopyTo(zip);
   }
   compressedBytes = mso.ToArray();
}

As others have said, you need to close the GZipStream before you can get the full data. 正如其他人所说,您需要关闭GZipStream才能获得完整数据。 A using statement will cause the Dispose method to be called on the stream at the end of the block, which will close the stream if it is not already closed. using语句将导致在块结尾处的流上调用Dispose方法,如果流尚未关闭,它将关闭流。 All of your examples above will work as expected if you place zip.Close(); 如果您放置zip.Close();上面的所有示例都将按预期工作zip.Close(); after msi.CopyTo(zip); msi.CopyTo(zip); .

You can eliminate one of the MemoryStreams if you write it this way: 如果以这种方式编写,可以删除其中一个MemoryStream:

using (MemoryStream mso = new MemoryStream())
{
    using (GZipStream zip = new GZipStream(mso, CompressionMode.Compress))
    {
        zip.Write(bytes, 0, bytes.Length);
    }
    compressedBytes = mso.ToArray();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM