DeflateStream не работает на MemoryStream?

у меня есть следующий фрагмент кода:

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 всегда пусто!

что я делаю неправильно здесь?

3 ответов


поместите свою проверку 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()s в writeline.

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

обратное так же просто, но вам понадобится оценка максимальной длины для создания read-buffer:

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

вот ведь DeflateStream не сбрасывает данные в базовый поток, пока он не будет закрыт. После того, как он закрыт,resultStream будет содержать сжатые данные. Обратите внимание, что по умолчанию DeflateStream закрывает базовый поток, когда он закрыт, но вы этого не хотите, поэтому вам нужно передать true на


из исходного ответа (у меня недостаточно кредитов, чтобы проголосовать)

поместите свой контроль WriteLine вне using

это неполно и вводит в заблуждение. DeflateStream закрывается после того, как базовых resultStream DeflateStream выходит из области видимости. Поэтому resultStream.Длина бросков

Unhandled Exception: System.ObjectDisposedException: Cannot access a closed Stream.

Томас Левек прав => также установить leaveOpen в true.

интересный вопрос с хорошими точки, поднятые HH и TL.