我有以下代码:
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总是空的!
我在这里做错什么了?
发布于 2013-08-30 19:30:44
将您的验证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);此外,你不需要所有的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();
}相反的操作也同样容易,但是您需要估计最大长度才能创建读取缓冲区:
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);
}
}发布于 2013-08-30 19:39:17
这是因为在数据关闭之前,DeflateStream不会将数据刷新到底层流。关闭后,resultStream将包含压缩数据。注意,默认情况下,当底层流关闭时,DeflateStream会关闭它,但是您不想这样做,所以您需要为leaveOpen参数传递true。另外,您不需要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
} 发布于 2015-02-10 11:55:39
从最初的答案来看(我没有足够的学分去投票)
将您的控件WriteLine放在使用
,这是不完整的,因此海事组织误导了。DeflateStream的Dispose(bool) implementation Close是垃圾收集后DeflateStream被Finalized时的底层resultStream。当这种情况发生时,resultStream.Length会抛出:
Unhandled Exception: System.ObjectDisposedException: Cannot access a closed Stream.换句话说,Thomas的注释是至关重要的:还将设置为 true.
这是一个有趣的问题,有HH和TL提出的一些好的观点。
https://stackoverflow.com/questions/18540125
复制相似问题