2008-09-16 107 views
442

如果我得到的MemoryStream我知道已填充String,我怎样才能得到String退出?如何从MemoryStream获取字符串?

+1

无法完全确定,如果reader.close始终是必需的。我过去遇到过问题,所以我一直只是为了安全起见。 – Crusty 2008-09-16 23:15:29

回答

411

此示例显示如何读取和写入字符串到MemoryStream。


Imports System.IO 

Module Module1 
    Sub Main() 
    ' We don't need to dispose any of the MemoryStream 
    ' because it is a managed object. However, just for 
    ' good practice, we'll close the MemoryStream. 
    Using ms As New MemoryStream 
     Dim sw As New StreamWriter(ms) 
     sw.WriteLine("Hello World") 
     ' The string is currently stored in the 
     ' StreamWriters buffer. Flushing the stream will 
     ' force the string into the MemoryStream. 
     sw.Flush() 
     ' If we dispose the StreamWriter now, it will close 
     ' the BaseStream (which is our MemoryStream) which 
     ' will prevent us from reading from our MemoryStream 
     'sw.Dispose() 

     ' The StreamReader will read from the current 
     ' position of the MemoryStream which is currently 
     ' set at the end of the string we just wrote to it. 
     ' We need to set the position to 0 in order to read 
     ' from the beginning. 
     ms.Position = 0 
     Dim sr As New StreamReader(ms) 
     Dim myStr = sr.ReadToEnd() 
     Console.WriteLine(myStr) 

     ' We can dispose our StreamWriter and StreamReader 
     ' now, though this isn't necessary (they don't hold 
     ' any resources open on their own). 
     sw.Dispose() 
     sr.Dispose() 
    End Using 

    Console.WriteLine("Press any key to continue.") 
    Console.ReadKey() 
    End Sub 
End Module 
+3

是不是要抛弃StreamWriter函数是否超出范围? – 2010-01-25 17:15:01

32

使用StreamReader,那么你可以使用ReadToEnd方法返回一个字符串。

+10

我只想提一提,`Basestream`应该已经将其位置设置为0.就像`memoryStream.Position = 0;`一样。 – 2011-12-14 14:44:58

96

使用StreamReader将MemoryStream转换为字符串。

<Extension()> _ 
Public Function ReadAll(ByVal memStream As MemoryStream) As String 
    ' Reset the stream otherwise you will just get an empty string. 
    ' Remember the position so we can restore it later. 
    Dim pos = memStream.Position 
    memStream.Position = 0 

    Dim reader As New StreamReader(memStream) 
    Dim str = reader.ReadToEnd() 

    ' Reset the position so that subsequent writes are correct. 
    memStream.Position = pos 

    Return str 
End Function 
+3

将Position设置为0会限制方法的重用能力 - 最好让调用者管理它。如果流包含字符串之前的数据,那么调用者知道如何处理? – 2008-09-17 00:41:08

+1

using语句将确保您的StreamReader得到处理,但文档说StreamReader在处理时关闭了基础流。因此,您的方法会关闭它传递的MemoryStream,即使我怀疑MemoryStream.Dispose执行得太多,对于调用者来说这在概念上并不酷。 – Trillian 2009-08-28 22:23:55

+0

你是对的。在流助手类中使用Dispose方法通常是一个糟糕的主意,特别是如果流作为参数传递给方法时。我会更新这个答案。下面我还有一个更完整的答案。 – Brian 2009-09-02 18:35:19

231

您还可以使用

Encoding.ASCII.GetString(ms.ToArray()); 

我不认为是低效率的,但我不能发誓它。它也可以让你选择不同的编码,而使用StreamReader时你必须指定它作为参数。

5

Brian的答案的稍微修改版本允许可选的管理读取开始,这似乎是最简单的方法。可能不是最高效的,但容易理解和使用。

Public Function ReadAll(ByVal memStream As MemoryStream, Optional ByVal startPos As Integer = 0) As String 
    ' reset the stream or we'll get an empty string returned 
    ' remember the position so we can restore it later 
    Dim Pos = memStream.Position 
    memStream.Position = startPos 

    Dim reader As New StreamReader(memStream) 
    Dim str = reader.ReadToEnd() 

    ' reset the position so that subsequent writes are correct 
    memStream.Position = Pos 

    Return str 
End Function 
17

以前的解决方案不适用于涉及编码的情况。这是 - 种“现实生活”的 - 例如如何正确地做到这一点...

using(var stream = new System.IO.MemoryStream()) 
{ 
    var serializer = new DataContractJsonSerializer(typeof(IEnumerable<ExportData>), new[]{typeof(ExportData)}, Int32.MaxValue, true, null, false);    
    serializer.WriteObject(stream, model); 


    var jsonString = Encoding.Default.GetString((stream.ToArray())); 
} 
10

在这种情况下,如果你真的想在MemoryStream使用ReadToEnd方法有一个简单的方法,你可以使用这个扩展方法来实现这一目标:

public static class SetExtensions 
{ 
    public static string ReadToEnd(this MemoryStream BASE) 
    { 
     BASE.Position = 0; 
     StreamReader R = new StreamReader(BASE); 
     return R.ReadToEnd(); 
    } 
} 

你可以以这种方式使用此方法:

using (MemoryStream m = new MemoryStream()) 
{ 
    //for example i want to serialize an object into MemoryStream 
    //I want to use XmlSeralizer 
    XmlSerializer xs = new XmlSerializer(_yourVariable.GetType()); 
    xs.Serialize(m, _yourVariable); 

    //the easy way to use ReadToEnd method in MemoryStream 
    MessageBox.Show(m.ReadToEnd()); 
} 
5

为什么不上MemoryStream的类型一种很好的扩展方法是什么?

public static class MemoryStreamExtensions 
{ 

    static object streamLock = new object(); 

    public static void WriteLine(this MemoryStream stream, string text, bool flush) 
    { 
     byte[] bytes = Encoding.UTF8.GetBytes(text + Environment.NewLine); 
     lock (streamLock) 
     { 
      stream.Write(bytes, 0, bytes.Length); 
      if (flush) 
      { 
       stream.Flush(); 
      } 
     } 
    } 

    public static void WriteLine(this MemoryStream stream, string formatString, bool flush, params string[] strings) 
    { 
     byte[] bytes = Encoding.UTF8.GetBytes(String.Format(formatString, strings) + Environment.NewLine); 
     lock (streamLock) 
     { 
      stream.Write(bytes, 0, bytes.Length); 
      if (flush) 
      { 
       stream.Flush(); 
      } 
     } 
    } 

    public static void WriteToConsole(this MemoryStream stream) 
    { 
     lock (streamLock) 
     { 
      long temporary = stream.Position; 
      stream.Position = 0; 
      using (StreamReader reader = new StreamReader(stream, Encoding.UTF8, false, 0x1000, true)) 
      { 
       string text = reader.ReadToEnd(); 
       if (!String.IsNullOrEmpty(text)) 
       { 
        Console.WriteLine(text); 
       } 
      } 
      stream.Position = temporary; 
     } 
    } 
} 

当然,在将这些方法与标准方法结合使用时要小心。 :) ...如果需要,您需要使用那个方便的streamLock,以实现并发性。

10

此示例显示如何从MemoryStream中读取一个字符串,其中我使用了序列化(使用DataContractJsonSerializer),将字符串从某个服务器传递到客户端,然后如何从传递的字符串中恢复MemoryStream作为参数,然后反序列化MemoryStream。

我已经使用不同职位的部分来执行此示例。

希望这可以帮助。

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Runtime.Serialization; 
using System.Runtime.Serialization.Json; 
using System.Threading; 

namespace JsonSample 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var phones = new List<Phone> 
      { 
       new Phone { Type = PhoneTypes.Home, Number = "28736127" }, 
       new Phone { Type = PhoneTypes.Movil, Number = "842736487" } 
      }; 
      var p = new Person { Id = 1, Name = "Person 1", BirthDate = DateTime.Now, Phones = phones }; 

      Console.WriteLine("New object 'Person' in the server side:"); 
      Console.WriteLine(string.Format("Id: {0}, Name: {1}, Birthday: {2}.", p.Id, p.Name, p.BirthDate.ToShortDateString())); 
      Console.WriteLine(string.Format("Phone: {0} {1}", p.Phones[0].Type.ToString(), p.Phones[0].Number)); 
      Console.WriteLine(string.Format("Phone: {0} {1}", p.Phones[1].Type.ToString(), p.Phones[1].Number)); 

      Console.Write(Environment.NewLine); 
      Thread.Sleep(2000); 

      var stream1 = new MemoryStream(); 
      var ser = new DataContractJsonSerializer(typeof(Person)); 

      ser.WriteObject(stream1, p); 

      stream1.Position = 0; 
      StreamReader sr = new StreamReader(stream1); 
      Console.Write("JSON form of Person object: "); 
      Console.WriteLine(sr.ReadToEnd()); 

      Console.Write(Environment.NewLine); 
      Thread.Sleep(2000); 

      var f = GetStringFromMemoryStream(stream1); 

      Console.Write(Environment.NewLine); 
      Thread.Sleep(2000); 

      Console.WriteLine("Passing string parameter from server to client..."); 

      Console.Write(Environment.NewLine); 
      Thread.Sleep(2000); 

      var g = GetMemoryStreamFromString(f); 
      g.Position = 0; 
      var ser2 = new DataContractJsonSerializer(typeof(Person)); 
      var p2 = (Person)ser2.ReadObject(g); 

      Console.Write(Environment.NewLine); 
      Thread.Sleep(2000); 

      Console.WriteLine("New object 'Person' arrived to the client:"); 
      Console.WriteLine(string.Format("Id: {0}, Name: {1}, Birthday: {2}.", p2.Id, p2.Name, p2.BirthDate.ToShortDateString())); 
      Console.WriteLine(string.Format("Phone: {0} {1}", p2.Phones[0].Type.ToString(), p2.Phones[0].Number)); 
      Console.WriteLine(string.Format("Phone: {0} {1}", p2.Phones[1].Type.ToString(), p2.Phones[1].Number)); 

      Console.Read(); 
     } 

     private static MemoryStream GetMemoryStreamFromString(string s) 
     { 
      var stream = new MemoryStream(); 
      var sw = new StreamWriter(stream); 
      sw.Write(s); 
      sw.Flush(); 
      stream.Position = 0; 
      return stream; 
     } 

     private static string GetStringFromMemoryStream(MemoryStream ms) 
     { 
      ms.Position = 0; 
      using (StreamReader sr = new StreamReader(ms)) 
      { 
       return sr.ReadToEnd(); 
      } 
     } 
    } 

    [DataContract] 
    internal class Person 
    { 
     [DataMember] 
     public int Id { get; set; } 
     [DataMember] 
     public string Name { get; set; } 
     [DataMember] 
     public DateTime BirthDate { get; set; } 
     [DataMember] 
     public List<Phone> Phones { get; set; } 
    } 

    [DataContract] 
    internal class Phone 
    { 
     [DataMember] 
     public PhoneTypes Type { get; set; } 
     [DataMember] 
     public string Number { get; set; } 
    } 

    internal enum PhoneTypes 
    { 
     Home = 1, 
     Movil = 2 
    } 
} 
8
byte[] array = Encoding.ASCII.GetBytes("MyTest1 - MyTest2"); 
MemoryStream streamItem = new MemoryStream(array); 

// convert to string 
StreamReader reader = new StreamReader(streamItem); 
string text = reader.ReadToEnd();