Еще одна проблема распаковки DeflateStream (использование потоков и памяти) - PullRequest
1 голос
/ 02 сентября 2011

Во-первых, я замечаю, что сжатие объекта требует больше байтов, чем просто представление объекта в двоичной форме.(228 против 166).

Во-вторых, я не могу распаковать его.

Кроме того, я не могу использовать хорошую функциональность CopyTo, так как у меня нет версии 4.NET framework.

Что нужно сделать в последнем DeflateStream с использованием блока?

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

Ответы [ 2 ]

3 голосов
/ 02 сентября 2011

Нет никакой гарантии, что выкачивание всегда приведет к уменьшению размера (хотя должно просто использовать в таких случаях секцию "сохранено / необработанное / нефиксированное").

Реализация .NET deflate (которая также используется в GZipStream) известна как особенно плохая (хотя и соответствует) при кодировании небольших и / или уже сжатых данных.Существуют сторонние библиотеки, в том числе DotNetZip, которые исправляют эти две проблемы, присутствующие в .NET BCL.

Когда я выполняю дефляционное сжатие (для небольших фрагментов данных), у меня есть флаг «дефлированный», поэтому поток IХранилище только иногда сдувается, в зависимости от того, стоило ли это сдувать.

Счастливое кодирование.

0 голосов
/ 02 сентября 2011

Вы можете инициализировать поток памяти с байтами, уже подобными этому (нет необходимости записывать и позиционировать):

Код внутри - это то, что CopyTo делает в .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();
}

Я получил этот код по причине (удаление уведомления). Я думаю, я помню, что он не работал, когда я пытался утилизировать его с помощью using output, что определенно выглядело бы круче.

...