Yet another DeflateStream decompression problem (using using and memory streams)
Firstly, I'm noticing that compressing the object requires more bytes then purely representing the object in binary form. (228 vs 166).
Secondly, I can't seem to decompress it.
Also, I can't use the nice CopyTo functionality since I don't have version 4 of the .NET framework.
What needs to go in the last DeflateStream using block?
MyClass MyObj = new MyClass();
MyObj.MyProp1 = true;
MyObj.MyProp2 = "Dee";
MyClass MyObAfterSerDeser = null;
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, MyObj);
byte[] prebytes = ms.ToArray(); // length 166.
ms.SetLength(0L);
using(MemoryStream tmpms = new MemoryStream())
{
using (DeflateStream dsc = new DeflateStream(tmpms, CompressionMode.Compress))
开发者_如何学运维 {
dsc.Write(prebytes, 0, prebytes.Length);
tmpms.WriteTo(ms); // unforunately though, just want the # of compressed bytes.
}
}
byte[] cbytes = ms.ToArray(); // length 228. Longer than uncompressed version!
ms.SetLength(0L);
using (MemoryStream tmpms = new MemoryStream())
{
tmpms.Write(cbytes, 0, cbytes.Length);
tmpms.Position = 0;
using (DeflateStream dsd = new DeflateStream(tmpms, CompressionMode.Decompress))
{
byte[] dbytes = new byte[cbytes.Length];
dsd.Read(dbytes, 0, dbytes.Length);
int offset = ReadAllBytesFromStream(dsd, dbytes); // written by Mr. Skeet.
// dsd.Write(dbytes, 0, cbytes.Length);
// dsd.Read(dbytes, 0, dbytes.Length);
ms.Write(dbytes, 0, offset);
}
}
MyObAfterSerDeser = (MyClass)bf.Deserialize(ms);
}
There is no guarantee that deflate will always result in a smaller size (although it should just use a "stored/raw/undeflated" section in such cases).
The .NET deflate implementation (which is also used in the GZipStream) is known to be particular bad (although conforming) when encoding small and/or already compressed data. There are 3rd party libraries, including DotNetZip, that correct these two issues present in the .NET BCL.
When I do deflate compression (on small pieces of data) I have a "deflated" flag so the stream I store is only sometimes deflated, depending upon if the deflate was "worth it".
Happy coding.
You can initialize memorystream with bytes already like this (no need to write & position):
Code inside is what CopyTo does in .NET 4.0
MemoryStream output = new MemoryStream();
try
{
using (MemoryStream ms = new MemoryStream(cbytes))
using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress, true)) {
int num;
byte[] buffer = new byte[100];
while ((num = ds.Read(buffer, 0, buffer.Length)) != 0)
{
output.Write(buffer, 0, num);
}
}
MyObAfterSerDeser = (MyClass)bf.Deserialize(output);
}
finally
{
output.Dispose();
}
I got this code for a reason (notice dispose) I believe, I remember it was not working when I was trying to Dispose it by means of using output
instead which definately would look cooler.
精彩评论