8

У меня есть следующий фрагмент кода: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 всегда пусто!

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

ответ

9

Поместите свою проверку 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(); 
} 

Обратное так же легко, но вам потребуется оценка максимальной длины для создания чтения-буфера:

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

thats it! tks alot! я буду принимать как ответ в минуту – Leonardo

+0

Хорошо. Обязательно прочитайте ответ Томаса об устранении 1 MemoryStream, и вы также можете заменить Formatter на 'Encoding.GetBytes()'. –

7

Это потому, что DeflateStream не очищает данные до основного потока до его закрытия. После его закрытия resultStream будет содержать сжатые данные. Обратите внимание, что по умолчанию DeflateStream закрывает базовый поток, когда он закрыт, но вы этого не хотите, поэтому вам необходимо передать true для параметра leaveOpen. Кроме того, вам не нужно 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 
    } 
+2

Поток не должен оставаться открытым, ToArray() отлично работает на закрытом MemoryStream. Но согласился на сериализацию напрямую. –

+0

@ ХенкХолтерман, ты прав; Я получал исключение при доступе к потоку потока, но ToArray отлично работает. –

3

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

Put ваш контроль WriteLine снаружи с помощью

это является неполным и вводящим в заблуждение. DeflateStream закрывает базовый результатStream, как только DeflateStream выходит за рамки. Поэтому resultStream.Length бросает

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

Thomas Levesque правильно => также установить leaveOpen истина.

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

+0

Я не видел этого раньше, но доступ к потоку после его удаления довольно неплохо, __a долго, поскольку это MemoryStream__. Это было непонятно в моем первом фрагменте, но во втором, более длинном и в вопросе. –

+0

Спасибо за обновление; отметил :-) –

 Смежные вопросы

  • Нет связанных вопросов^_^