我已经编写了一些使用Gzip或Deflate压缩和解压缩数据的代码(都在System.IO.Compression中),我在.NetCore项目中测试了它,它工作正常并且所有测试用例都通过了。所以我在.Net 4.6.2项目中回收了相同的代码,尽管msdn文档说它兼容,但我仍然遇到问题。在这里,你是我讨论的代码部分
public virtual byte[] Encode<TObject>(TObject objectToEncode) where TObject : class, new()
{
if (objectToEncode == null) throw new ArgumentNullException(nameof(objectToEncode));
byte[] jsonResult = null;
using (var ms = new MemoryStream())
{
//Generazione del Json
using (var textWriter = new StreamWriter(ms, System.Text.Encoding.UTF8))
{
using (var jsonWriter = new JsonTextWriter(textWriter))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(jsonWriter, objectToEncode, objectToEncode.GetType());
jsonWriter.Flush();
textWriter.Flush();
ms.Flush();
//Compressione Json
jsonResult = ms.ToArray();
}
}
}
using (var msResult = new MemoryStream())
{
using (var encodingStream = GenerateEncodingStream(msResult))
{
encodingStream.Write(jsonResult, 0, Convert.ToInt32(jsonResult.Length));
encodingStream.Flush();
msResult.Position = 0;
return msResult.ToArray();
}
}
}
GenerateEncondingStream只需调用DeflateStream或Gzipstream的构造函数,具体取决于您选择的构造函数。
问题: 如果我使用Deflate,msResult.Lenght是0个单元格,而如果我使用GZip长度msResult.Length是同一数据集的10个单元格(.NetCore项目中都是211)。
大量使用Flush()是为了确保每个流都完全刷新到应有的位置。 是否存在.Net 4.6.2的问题或者我的代码错了?谢谢你的帮助!
编辑: 同样的问题,但是解压缩和反序列化:如果我解压缩然后在关闭所有流后反序列化,我的性能比下面列出的使用封装流的版本高出10%。 在解压缩时,下面的代码在反序列化时失败。 我没有想法,因为具有10%效率的版本是不可接受的......
public virtual async Task<object> DecodeAsync(byte[] encodedObject, Type decodedObjectType, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (encodedObject == null) throw new ArgumentNullException(nameof(encodedObject));
if (encodedObject.Length == 0) throw new ArgumentException(nameof(encodedObject));
using (var compressedStream = new MemoryStream(encodedObject))
{
using (var csStream = GenerateDecodingStream(compressedStream))
{
using (var decompressedStream = new MemoryStream())
{
using (StreamReader sr = new StreamReader(decompressedStream, System.Text.Encoding.UTF8))
{
using (var reader = new JsonTextReader(sr))
{
JsonSerializer serializer = new JsonSerializer();
return serializer.Deserialize(reader, decodedObjectType);
}
}
}
}
}
}
答案 0 :(得分:4)
在reference source of DeflateStream
中,Flush()
无法执行任何操作。
查看反射器,常见的.NET Framework Flush()
也是如此。所以基本上,Flush()
不想刷新 - 大概是为了最大限度地提高压缩效率。相反,仅在数据大小足够大或处置时才会进行刷新。
相比之下,在.NET Core源代码中,Flush()
actually flushes。
所以:在您关闭包含.ToArray()
的所有内容之后,将您的MemoryStream
来电转移到 。
所以:
using (var ms = new MemoryStream())
{
//Generazione del Json
using (var textWriter = new StreamWriter(ms, System.Text.Encoding.UTF8))
{
using (var jsonWriter = new JsonTextWriter(textWriter))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(jsonWriter, objectToEncode, objectToEncode.GetType());
}
}
jsonResult = ms.ToArray();
}
using (var msResult = new MemoryStream())
{
using (var encodingStream = GenerateEncodingStream(msResult))
{
encodingStream.Write(jsonResult, 0, Convert.ToInt32(jsonResult.Length));
}
return msResult.ToArray();
}