如何从 MemoryStream 中获取字符串?

How do you get a string from a MemoryStream?

提问人:Brian 提问时间:9/17/2008 最后编辑:Erik SchierboomBrian 更新时间:10/12/2023 访问量:563237

问:

如果给我一个我知道已经填充了 ,我该如何获得一个?MemoryStreamStringString

.NET vb.net 字符串 MemoryStream

评论

1赞 Crusty 9/17/2008
永远不确定是否始终需要 reader.close。我过去也遇到过问题,所以通常我总是这样做只是为了安全起见。

答:

46赞 Darren Kopp 9/17/2008 #1

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

评论

17赞 Aykut Çevik 12/14/2011
我只想提一下,应该将其位置设置为 0。喜欢。BasestreammemoryStream.Position = 0;
105赞 Brian 9/17/2008 #2

使用 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赞 Alex Lyman 9/17/2008
将 Position 设置为 0 会限制方法的重用能力 -- 最好让调用方来管理。如果流在字符串之前包含调用方知道如何处理的数据,该怎么办?
1赞 Trillian 8/29/2009
using 语句将确保您的 StreamReader 被释放,但文档说 StreamReader 在释放时会关闭基础流。因此,您的方法会关闭它传递的 MemoryStream,即使我怀疑 MemoryStream.Dispose 做了很多事情,这在概念上对调用者来说也是不酷的。
0赞 Brian 9/3/2009
你是对的。在流帮助程序类上使用 Dispose 方法通常是一个坏主意,尤其是在将流作为参数传递到方法时。我会更新这个答案。我在下面也有更完整的答案。
0赞 Sinaesthetic 9/25/2013
如果反编译这些类,你将看到 dispose 方法只是在实例中不为 null 的任何流(TextWriter、MemoryStream 等)上调用 Dispose()
496赞 Brian 9/30/2008 #3

此示例演示如何读取字符串并将其写入 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

评论

4赞 Tim Keating 1/26/2010
无论如何,当函数超出范围时,它不会处理 StreamWriter 吗?
19赞 Brian 1/27/2010
当变量超出范围时,不调用 Dispose。当 GC 处理它时,将调用 Finalize,但 Dispose 是在变量超出范围之前必须调用的。我没有在上面调用它,因为我知道 StreamWriter 和 StreamReader 的实现不需要调用 Dispose,它只是将调用传递给底层流。但是,对于实现 IDisposable 的任何内容调用 Dipose,可以提出一个合理的论据,因为无法保证将来的版本不需要释放它。
13赞 Rowland Shaw 4/30/2012
@MichaelEakins 当问题被标记为 VB.Net 时,为什么答案甚至应该用 C# ?
1赞 Gerard ONeill 7/18/2013
我很高兴我了解了“帮助程序”将 dispose 调用传递给其底层流,但这似乎是一个糟糕的设计决策。
2赞 Mark Sowul 2/4/2016
这个决定后来得到了缓解:msdn.microsoft.com/en-us/library/......
386赞 Coderer 10/25/2008 #4

您还可以使用

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

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

评论

17赞 northben 1/15/2014
编码位于 System.Text 命名空间中
3赞 Lewis 1/15/2015
我正在寻找与此等效的 PowerShell,并且不得不使用它。([System.Text.Encoding]::ASCII)。GetString(ms.ToArray())
5赞 Grant H. 8/5/2016
FWIW,我发现这不适用于非常大的字符串,我得到了 s。使用 a 代替了这个问题。OutOfMemoryExceptionStreamReader
2赞 Jirapong 11/24/2020
如果你的内容是UTF8,你也可以System.Text.UTF8.GetString(ms.ToArray())
3赞 Beauty 11/26/2020
@Jirapong,在 2020 年使用 UTF8 是一个很好的评论,但在 .NET Framework 4.x 上,您的代码不起作用。相反,它成功了。也许你的代码是错误的或以 .NET Core 为目标?不过:谢谢!Encoding.UTF8.GetString(ms.ToArray()
6赞 James 4/7/2010 #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

评论

3赞 Luis Filipe 7/25/2011
它真的没有给布莱恩的答案增加任何新东西
27赞 Arek Bal 10/26/2012 #6

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

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()));
}
23赞 Mehdi Khademloo 10/25/2014 #7

在这种情况下,如果你真的想以一种简单的方式使用方法,你可以使用这个扩展方法来实现这一点:ReadToEndMemoryStream

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

评论

2赞 feradz 11/30/2022
设置帮助了我。Position = 0
7赞 Alexandru 11/13/2014 #8

为什么不在 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 来实现并发性。

11赞 Sebastian Ferrari 7/16/2015 #9

此示例演示如何从 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
    }
}
38赞 Sadjad Khazaie 5/4/2017 #10
byte[] array = Encoding.ASCII.GetBytes("MyTest1 - MyTest2");
MemoryStream streamItem = new MemoryStream(array);

// convert to string
StreamReader reader = new StreamReader(streamItem);
string text = reader.ReadToEnd();
1赞 Riccardo Bassilichi 4/14/2020 #11

我需要与一个需要 Stream 才能写入的类集成:

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);
-1赞 Harlin Acero 12/14/2020 #12

仅使用方法 Convert.ToBase64String

Convert.ToBase64String(inputStream.ToArray());

评论

4赞 AaA 5/18/2021
如果内容只是明文,为什么要使用 ToBase64String?
-1赞 Sumanth Kumar 10/12/2023 #13

创建一个 StreamReader 对象以从 MemoryStream 对象读取数据。

StreamReader reader = new StreamReader(memoryStream);

将 MemoryStream 对象读取到字符串。

memoryStreamValue = 读取器。ReadToEnd();

关闭 StreamReader obj。

读者。关闭();

评论

1赞 nalka 10/12/2023
您的答案没有提供比现有答案更多的信息,我认为您应该阅读帮助中心以获取答案,尤其是如何回答?导致答案删除的原因