C# DeflateStream对MemoryStream不起作用?

C# DeflateStream对MemoryStream不起作用?,c#,serialization,memorystream,deflate,binary-serialization,C#,Serialization,Memorystream,Deflate,Binary Serialization,我有以下代码: MemoryStream resultStream = new MemoryStream(); string users = ""//Really long string goes here BinaryFormatter bFormatter = new BinaryFormatter(); using (MemoryStream assignedUsersStream = new MemoryStream()) { bFormatter.Serialize(assig

我有以下代码:

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
总是空的


我在这里做错了什么?

将您的验证写入线放在使用之外。缓冲区尚未刷新

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);
除此之外,您不需要在writeline中使用所有这些
ToString()
s

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

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();
}
反之亦然,但您需要估计最大长度以创建读取缓冲区:

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);                        
    }                    
}

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

    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
    } 
从最初的答案来看(我没有足够的学分去投票否决)

将控件写入线置于使用

这是不完整和误导的。一旦DeflateStream超出范围,DeflateStream将关闭底层resultStream。因此resultStream.Length抛出

Unhandled Exception: System.ObjectDisposedException: Cannot access a closed Stream.
Thomas Levesque正确=>还将
leaveOpen
设置为true


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

流不必保持打开状态,ToArray()在一个关闭的内存流上可以很好地工作。但同意直接连载。@Henkholtman,你说得对;当访问流的长度时,我遇到了一个异常,但是ToArray可以正常工作。很好。请务必阅读Thomas关于删除1个MemoryStream的回答,您还可以使用
Encoding.GetBytes()
替换格式化程序。我以前没有看到这一点,但在处理后访问流是完全正确的,只要它是一个MemoryStream。这在我的第一段中并不清楚,但在第二段中,更长的一段和问题中。