2012-05-04 39 views
31

Tôi đang cố viết đối tượng vào chuỗi Xml và lấy chuỗi đó và lưu nó vào DB. Nhưng trước tiên, tôi cần phải nhận được chuỗi ...Đọc từ luồng bộ nhớ thành chuỗi

private static readonly Encoding LocalEncoding = Encoding.UTF8; 

    public static string SaveToString<T> (T settings) 
    { 
     Stream stream = null; 
     TextWriter writer = null; 
     string settingsString = null; 

     try 
     { 
      stream = new MemoryStream(); 

      var serializer = new XmlSerializer(typeof(T)); 

      writer = new StreamWriter(stream, LocalEncoding); 

      serializer.Serialize(writer, settings); 

      var buffer = new byte[stream.Length]; 

      stream.Read(buffer, 0, (int)stream.Length); 

      settingsString = LocalEncoding.GetString(buffer); 
     } 
     catch(Exception ex) 
     { 
      // If the action cancels we don't want to throw, just return null. 
     } 
     finally 
     { 
      if (stream != null) 
       stream.Close(); 

      if(writer != null) 
       writer.Close(); 
     } 

     return settingsString; 
    } 

Điều này dường như hoạt động, luồng được lấp đầy bằng byte. Nhưng khi tôi đến để đọc nó trở lại vào bộ đệm và sau đó vào chuỗi ... bộ đệm được làm đầy với '0'! Không chắc tôi làm gì ở đây.

+1

thể trùng lặp của [Làm thế nào để bạn có được một chuỗi từ một MemoryStream?] (Http://stackoverflow.com/questions/78181/how-do-you-get-a-string-from -a-memorystream) – andyp

Trả lời

64

Nếu bạn đã kiểm tra kết quả của stream.Read, bạn đã thấy rằng nó chưa đọc bất kỳ điều gì - bởi vì bạn chưa tua lại luồng. (Bạn có thể làm điều này với stream.Position = 0;.) Tuy nhiên, nó dễ dàng hơn để chỉ cần gọi ToArray:

settingsString = LocalEncoding.GetString(stream.ToArray()); 

(Bạn sẽ cần phải thay đổi loại stream từ Stream để MemoryStream, nhưng đó là okay vì nó là trong cùng một phương pháp nơi bạn tạo ra nó.)

Cách khác - và thậm chí đơn giản hơn - chỉ cần sử dụng StringWriter thay vì StreamWriter. Bạn sẽ cần phải tạo một lớp con nếu bạn muốn sử dụng UTF-8 thay vì UTF-16, nhưng điều đó khá dễ dàng. Xem this answer để biết ví dụ.

Tôi quan tâm đến cách bạn chỉ cần bắt Exceptiongiả định rằng điều đó có nghĩa là điều gì đó vô hại, nhân tiện - thậm chí không cần ghi lại bất kỳ thứ gì. Lưu ý rằng các câu lệnh using thường sạch hơn viết các khối finally rõ ràng.

+0

Cảm ơn :). Đó là công việc nhanh chóng. Tôi biết các khối sử dụng bình thường hơn. Nhưng tôi khá giống như độ phẳng này mang lại cho tôi, không có sử dụng lồng nhau. Đó chỉ là một điều phong cách. Tôi không biết có một StringWriter, có vẻ dễ dàng hơn nhiều, nhưng tôi thích khả năng xác định encoing. Tôi có lẽ sẽ thêm một quá tải cho điều này, chứ không phải là một lớp mới. – tigerswithguitars

+0

@tigerswithguitars: Chính xác bạn định thêm quá tải vào 'StringWriter' như thế nào? Điểm của lớp mới là 'StringWriter' luôn trả về UTF-16 từ thuộc tính' TextWriter.Encoding' của nó; lớp thừa chỉ ghi đè thuộc tính đó. –

+0

xin lỗi, từ ngữ của tôi rất khó hiểu. Tôi sẽ thêm quá tải vào phương thức của riêng tôi để chỉ định mã hóa. – tigerswithguitars

8
string result = System.Text.Encoding.UTF8.GetString(fs.ToArray()); 
+1

Trong khi mẫu mã này có thể trả lời được câu hỏi, thì tốt nhất nên đưa ra một số giải thích cần thiết cho câu trả lời ở đây. –

+0

'Gốc' ở đây là gì? Nếu một biến, làm thế nào bạn bạn nhanh chóng nó? Cùng một câu hỏi cho 'fs'. –

+0

Người dùng đã nhầm lẫn sử dụng gốc thay vì Hệ thống – Prasanth

1
string result = Encoding.UTF8.GetString((stream as MemoryStream).ToArray()); 
+0

Tôi sẽ đặt câu hỏi về việc sử dụng 'as' ở đây - nó không bảo vệ bạn khỏi bất kỳ thứ gì. Đầu tiên, bạn biết luồng đó là 'MemoryStream', cộng thêm, ngay cả khi không, chuyển' null' vào 'GetString' sẽ ném một ngoại lệ, vì vậy bạn cũng có thể sử dụng một dàn diễn viên rõ ràng ngay từ đầu. –

+1

Mặc dù mã này có thể trả lời câu hỏi, cung cấp ngữ cảnh bổ sung về lý do và/hoặc cách mã này trả lời câu hỏi cải thiện giá trị lâu dài của nó. – ryanyuyu

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