2013-08-30 34 views
8

Tôi có đoạn mã sau:DeflateStream không hoạt động trên 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()); 
    } 
}    

điều là resultStream phải lúc nào cũng có sản phẩm nào!

Tôi đang làm gì sai ở đây?

Trả lời

9

Đặt xác minh của bạn WriteLine bên ngoài việc sử dụng. Bộ đệm chưa được xóa.

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

Và sang một bên, bạn không cần tất cả các bài viết đó ToString() s.

PS: Tất cả một BinaryFormatter thực hiện với một chuỗi là viết các byte có tiền tố độ dài. Nếu bạn không cần tiền tố (tôi đoán), nó có thể trở thành:

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

Điều ngược lại chỉ là dễ dàng nhưng bạn sẽ cần một ước lượng độ dài tối đa để tạo ra các read-đệm:

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 rất nhiều! tôi sẽ chấp nhận câu trả lời sau một phút – Leonardo

+0

Tốt. Hãy chắc chắn đọc câu trả lời của Thomas về việc loại bỏ 1 MemoryStream và bạn cũng có thể thay thế Formatter bằng 'Encoding.GetBytes()'. –

7

Đó là vì DeflateStream không tuôn ra dữ liệu đến luồng cơ bản cho đến khi nó được đóng lại. Sau khi đóng, resultStream sẽ chứa dữ liệu nén. Lưu ý rằng theo mặc định, DeflateStream đóng luồng cơ bản khi đóng, nhưng bạn không muốn điều đó, vì vậy bạn cần phải vượt qua true cho tham số leaveOpen. Ngoài ra, bạn không cần 2 dòng bộ nhớ, bạn chỉ có thể serialize trực tiếp đến 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

Luồng không cần phải mở, ToArray() sẽ hoạt động tốt trên MemoryStream đã đóng. Nhưng đồng ý về việc serializing trực tiếp. –

+0

@ HenkHolterman, bạn nói đúng; Tôi đã nhận được một ngoại lệ khi truy cập vào chiều dài của dòng, nhưng ToArray hoạt động tốt. –

3

Từ câu trả lời ban đầu (Tôi không có đủ tín dụng để bỏ phiếu xuống)

Đặt kiểm soát của bạn WriteLine bên ngoài việc sử dụng

Điều này không đầy đủ và gây hiểu lầm. DeflateStream đóng luồng kết quả cơ bản sau khi DeflateStream thoát khỏi phạm vi. Do đó resultStream.Length ném

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

Thomas Levesque là đúng => cũng đặt leaveOpen thành true.

Một câu hỏi thú vị với một số điểm tốt mà HH và TL nêu ra.

+0

Tôi không thấy điều này trước đây nhưng truy cập luồng sau khi xử lý nó hoàn toàn ổn định, __a miễn là nó là MemoryStream__. Điều đó không rõ ràng trong đoạn trích đầu tiên của tôi nhưng nó ở đoạn thứ hai, dài hơn và trong câu hỏi. –

+0

Cảm ơn bạn đã cập nhật; ghi chú :-) –

Các vấn đề liên quan