首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DeflateStream不在MemoryStream上工作吗?

DeflateStream不在MemoryStream上工作吗?
EN

Stack Overflow用户
提问于 2013-08-30 19:24:18
回答 4查看 13.3K关注 0票数 12

我有以下代码:

代码语言:javascript
复制
MemoryStream resultStream = new MemoryStream();
string users = ""//Really long string goes here
BinaryFormatter bFormatter = new BinaryFormatter();
using (MemoryStream assignedUsersStream = new MemoryStream())
{
    bFormatter.Serialize(assignedUsersStream, users);
    assignedUsersStream.Position = 0;

    using (var compressionStream =
        new DeflateStream(resultStream, CompressionLevel.Optimal))
    {
        assignedUsersStream.CopyTo(compressionStream);

        Console.WriteLine("Compressed from {0} to {1} bytes.",
            assignedUsersStream.Length.ToString(),
            resultStream.Length.ToString());
    }
}            

问题是resultStream总是空的!

我在这里做错什么了?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-08-30 19:30:44

将您的验证WriteLine放在使用之外。缓冲器还没冲过。

代码语言:javascript
复制
using (DeflateStream compressionStream = new DeflateStream(resultStream, CompressionLevel.Optimal))
{
    assignedUsersStream.CopyTo(compressionStream);

    //Console.WriteLine("Compressed from {0} to {1} bytes.",
    //       assignedUsersStream.Length.ToString(), resultStream.Length.ToString());
}

Console.WriteLine("Compressed from {0} to {1} bytes.",
     assignedUsersStream.Length, resultStream.ToArray().Length);

此外,你不需要所有的ToString()在一个书面形式。

PS: BinaryFormatter对字符串所做的一切就是用长度前缀写入字节。如果您不需要前缀(我猜),它可能变成:

代码语言:javascript
复制
string users = "";//Really long string goes here
byte[] result;  

using (MemoryStream resultStream = new MemoryStream())
{
    using (DeflateStream compressionStream = new DeflateStream(resultStream,
             CompressionLevel.Optimal))
    {
        byte[] inBuffer = Encoding.UTF8.GetBytes(users);
        compressionStream.Write(inBuffer, 0, inBuffer.Length);
    }
    result = resultStream.ToArray();
}

相反的操作也同样容易,但是您需要估计最大长度才能创建读取缓冲区:

代码语言:javascript
复制
string users2 = null;

using (MemoryStream resultStream = new MemoryStream(result))
{
    using (DeflateStream compressionStream = new  DeflateStream(resultStream,
            CompressionMode.Decompress))
    {
        byte[] outBuffer = new byte[2048];   // need an estimate here
        int length = compressionStream.Read(outBuffer, 0, outBuffer.Length);
        users2 = Encoding.UTF8.GetString(outBuffer, 0, length);                        
    }                    
}
票数 16
EN

Stack Overflow用户

发布于 2013-08-30 19:39:17

这是因为在数据关闭之前,DeflateStream不会将数据刷新到底层流。关闭后,resultStream将包含压缩数据。注意,默认情况下,当底层流关闭时,DeflateStream会关闭它,但是您不想这样做,所以您需要为leaveOpen参数传递true。另外,您不需要2个内存流,您可以直接序列化到compressionStream

代码语言:javascript
复制
    string users = ""; //Really long string goes here
    BinaryFormatter bFormatter = new BinaryFormatter();
    using (MemoryStream resultStream = new MemoryStream())
    {
        using (DeflateStream compressionStream = new DeflateStream(resultStream, CompressionLevel.Optimal, true))
        {
            bFormatter.Serialize(compressionStream, users);
            Console.WriteLine(resultStream.Length); // 0 at this point
        }
        Console.WriteLine(resultStream.Length); // now contains the actual length
    } 
票数 12
EN

Stack Overflow用户

发布于 2015-02-10 11:55:39

从最初的答案来看(我没有足够的学分去投票)

将您的控件WriteLine放在使用

,这是不完整的,因此海事组织误导了DeflateStreamDispose(bool) implementation Close是垃圾收集后DeflateStreamFinalized时的底层resultStream。当这种情况发生时,resultStream.Length会抛出:

代码语言:javascript
复制
Unhandled Exception: System.ObjectDisposedException: Cannot access a closed Stream.

换句话说,Thomas的注释是至关重要的:还将设置为 true.

这是一个有趣的问题,有HH和TL提出的一些好的观点。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18540125

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档