如何从内存流中获取字符串?

如果我给了一个MemoryStream,我知道已经填充了String,我如何得到一个String回来?

532015 次浏览

使用StreamReader,然后可以使用返回字符串的ReadToEnd方法。

使用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

这个示例展示了如何将字符串读写到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

你也可以使用

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

我不认为这是较低的效率,但我不能发誓它。它还允许您选择不同的编码,而使用StreamReader时,您必须将其指定为参数。

稍微修改了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

以前的解决方案在涉及编码的情况下不起作用。这是一个“现实生活”的例子,如何正确地做到这一点…

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

在这种情况下,如果你真的想在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());
}

为什么不在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。

这个示例展示了如何从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
}
}
byte[] array = Encoding.ASCII.GetBytes("MyTest1 - MyTest2");
MemoryStream streamItem = new MemoryStream(array);


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

我需要集成一个类,需要一个流写在它:

XmlSchema schema;
// ... Use "schema" ...


var ret = "";


using (var ms = new MemoryStream())
{
schema.Write(ms);
ret = Encoding.ASCII.GetString(ms.ToArray());
}
//here you can use "ret"
// 6 Lines of code

我创建了一个简单的类,可以帮助减少多次使用的代码行:

public static class MemoryStreamStringWrapper
{
public static string Write(Action<MemoryStream> action)
{
var ret = "";
using (var ms = new MemoryStream())
{
action(ms);
ret = Encoding.ASCII.GetString(ms.ToArray());
}


return ret;
}
}

然后可以用一行代码替换示例

var ret = MemoryStreamStringWrapper.Write(schema.Write);

只使用方法Convert。ToBase64String

Convert.ToBase64String(inputStream.ToArray());