2009-10-27 9 views
8

discussed before, khi BinaryReader hoặc BinaryWriter bị đóng, luồng cơ bản của nó cũng bị đóng (aargh). Hãy xem xét tình huống này: một thông thường R được chuyển qua MemoryStream, nói M; Tôi muốn viết một số công cụ để M và sau đó chuyển nó đến một thói quen khác để xử lý nhiều hơn (không nhất thiết phải viết). Để thuận tiện, tôi muốn bọc M trong BinaryWriter để viết. Sau khi viết, tôi đã hoàn thành với BinaryWriter nhưng không phải với M.Làm cách nào để "ngã" một luồng trong .NET?

void R(MemoryStream M) 
{ 
    using (B = new BinaryWriter(M)) 
    { 
     // write some stuff using B 
    } 

    S(M); // now pass M to another routine for further processing 
} 

Nhưng, tôi không thể bỏ BinaryStream mà không đóng M.

Hỏi: Có cách nào để thực hiện bất kỳ thao tác nào sau đây không?

  • trích xuất các byte tiềm ẩn [] từ một MemoryStream,
  • bản sao một Stream
  • mở lại một Stream sau khi nó được đóng
+0

Tôi không biết C#, nhưng trong Java, bạn chỉ đơn giản là từ bỏ mà không đóng BinaryWriter. Không phải việc sử dụng {...} xây dựng lực lượng có đóng không? Sau đó, không sử dụng cấu trúc đó! –

+0

P.S. Nhưng bạn cần phải đảm bảo bạn tuôn ra BinaryWriter trước khi bạn từ bỏ nó. –

Trả lời

2

Nhờ một số người đề xuất ToArray, tôi đã được dẫn đến câu trả lời đúng, đó là `M.GetBuffer '. ToArray không phải là quá xấu, nhưng nó

  • tạo một bản sao
  • được chỉ là một phần của bộ đệm

GetBuffer chỉ lấy một tham chiếu đến các byte tiềm ẩn [], đó là những gì tôi sau.

+0

Được chỉ ra trong câu trả lời của tôi ;) –

0

Một phần nào tiếp cận ngây thơ là sử dụng

byte buf[] = MemoryStream.ToArray(); 

Để sao chép nội dung luồng vào một mảng byte. Bạn có thể biến nó trở thành một dòng suối với

MemoryStream ms = new MemoryStream(buf); 
+0

Đáng chú ý: phương pháp này hoạt động trên luồng đã đóng cũng như luồng trực tiếp. –

2

Bạn có thể:

  • Gọi M.ToArray() để có được những dòng như một mảng các byte.
  • Subclass BinaryWriter và ghi đè phương thức Dispose để ngăn chặn bế mạc của con suối con
+0

+1 dành riêng cho ghi đè Vứt bỏ. –

+0

Bạn không thể tránh gọi điện thoại gần/Vứt bỏ? –

-1

Accoring để this M.Clone(); nên làm việc. Nhưng tôi có thể sai ...

+0

-1 để đăng lên trang web không cho phép xem nội dung miễn phí, điều này khá là vô dụng –

7

Bạn tốt hơn nên các byte tiềm ẩn [] buffer sử dụng

byte[] buffer = ms.GetBuffer(); 

Và sau đó sao chép các dữ liệu byte bằng cách sử dụng phương pháp Array.Copy(). Bạn có thể tạo một luồng mới với nó.

+0

Tôi không hiểu tại sao bạn lại nói tốt hơn là sử dụng GetBuffer và sau đó tạo bản sao bằng Array.Copy. Nếu tôi muốn một bản sao tôi chỉ sử dụng ToArray. –

+0

Từ MSDN doc Phương thức này bỏ qua các byte không sử dụng trong MemoryStream từ mảng. Để có được toàn bộ bộ đệm, hãy sử dụng phương thức GetBuffer. http://msdn.microsoft.com/en-us/library/system.io.memorystream.toarray.aspx –

+0

Ở trên "Phương pháp này" đề cập đến MemoryStream.ToArray() –

5

Bạn có thể sử dụng những thứ như MiscUtil.IO.NonClosingStreamWrapper trong MiscUtil, mà kết thúc tốt đẹp một Stream và chỉ đơn giản là bỏ qua Close/Dispose yêu cầu. Chỉ với mục đích này.

void R(MemoryStream M) 
{ 
    using (B = new BinaryWriter(new NonClosingStreamWrapper(M))) 
    { 
     // write some stuff using B 
    } 

    S(M); // now pass M to another routine for further processing 
}  
1

Chỉ cần thêm nó ở đây, một giải pháp rất đơn giản sẽ là không để Vứt bỏ() nhà văn.

void R(MemoryStream M) 
{ 
    B = new BinaryWriter(M); 

    // write some stuff using B   
    B.Flush(); 
    S(M); // now pass M to another routine for further processing 
} 

Bây giờ bạn chỉ phải lo lắng về việc giữ B trong phạm vi, nó sẽ ở trong R().

Đây có thể không phải là giải pháp tốt nhất ở đây, nhưng đáng lưu ý là người đọc và nhà văn không cần tự vứt bỏ.

+0

Cho phép hy vọng 'BinaryWriter' không đệm bất cứ điều gì, sau đó ... –

+0

Nhưng hãy chắc chắn rằng bạn gọi B.flush() sau khi bạn đã hoàn thành nó trong trường hợp nó đã không đẩy tất cả mọi thứ thông qua M. (Đó là những gì sẽ là cần thiết trong Java, không có ý tưởng về C#) –

+0

OK, Adrian & Marc, tôi quên Flush(). –