DeflateStream不能在MemoryStream上运行?

Leo*_*rdo 10 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(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());
    }
}            
Run Code Online (Sandbox Code Playgroud)

事情是resultStream永远是空的!

我在这做错了什么?

Hen*_*man 12

将您的验证WriteLine放在使用之外.缓冲区尚未刷新.

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);
Run Code Online (Sandbox Code Playgroud)

除此之外,你不需要所有那些ToString()在写作线上.

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();
}
Run Code Online (Sandbox Code Playgroud)

反过来也很简单,但您需要估计最大长度来创建读缓冲区:

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);                        
    }                    
}
Run Code Online (Sandbox Code Playgroud)


Tho*_*que 10

这是因为在DeflateStream关闭之前,数据不会将数据刷新到基础流.关闭后,resultStream将包含压缩数据.请注意,在默认情况下,DeflateStream关闭底层流时它关闭,但你不希望出现这种情况,所以你需要传递trueleaveOpen参数.此外,您不需要2个内存流,您可以直接序列化到compressionStream:

    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
    } 
Run Code Online (Sandbox Code Playgroud)

  • 流不必保持打开状态,ToArray()将在关闭的MemoryStream上正常工作.但同意直接序列化. (2认同)