C# 从内存流读取到字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10446194/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 13:55:03  来源:igfitidea点击:

Reading from memory stream to string

c#xml-serializationxmlserializermemorystream

提问by tigerswithguitars

I am trying to write an object to an Xml string and take that string and save it to a DB. But first I need to get the string...

我正在尝试将一个对象写入一个 Xml 字符串并获取该字符串并将其保存到数据库中。但首先我需要得到字符串......

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

This seems to work, the stream gets filled with bytes. But when I come to read it back into the buffer and then into the string... the buffer is filled with '0'! Not sure what I doing wrong here guys.

这似乎有效,流中充满了字节。但是当我将它读回缓冲区然后读入字符串时......缓冲区填充了'0'!不知道我在这里做错了什么家伙。

采纳答案by Jon Skeet

If you'd checked the results of stream.Read, you'd have seen that it hadn't read anything - because you haven't rewound the stream. (You could do this with stream.Position = 0;.) However, it's easier to just call ToArray:

如果您检查了 的结果stream.Read,您会发现它没有读取任何内容 - 因为您还没有回绕流。(你可以用 来做到这一点stream.Position = 0;。)但是,调用 更容易ToArray

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

(You'll need to change the type of streamfrom Streamto MemoryStream, but that's okay as it's in the same method where you create it.)

(您需要将streamfrom的类型更改为Streamto MemoryStream,但这没关系,因为它与您创建它的方法相同。)

Alternatively - and even more simply - just use StringWriterinstead of StreamWriter. You'll need to create a subclass if you want to use UTF-8 instead of UTF-16, but that's pretty easy. See this answerfor an example.

或者 - 甚至更简单 - 只需使用StringWriter而不是StreamWriter. 如果您想使用 UTF-8 而不是 UTF-16,则需要创建一个子类,但这很容易。有关示例,请参阅此答案

I'm concerned by the way you're just catching Exceptionand assumingthat it means something harmless, by the way - without even logging anything. Note that usingstatements are generally cleaner than writing explicit finallyblocks.

顺便说一下,我担心您只是在捕捉Exception假设它意味着无害的方式 - 甚至没有记录任何内容。请注意,using语句通常比编写显式finally块更干净。

回答by Farzad J

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

回答by evorios

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

回答by George Kargakis

In case of a very large stream length there is the hazard of memory leak due to Large Object Heap. i.e. The byte buffer created by stream.ToArray creates a copy of memory stream in Heap memory leading to duplication of reserved memory. I would suggest to use a StreamReader, a TextWriterand read the stream in chunks of charbuffers.

在非常大的流长度的情况下,由于大对象堆存在内存泄漏的危险。即由 stream.ToArray 创建的字节缓冲区在堆内存中创建内存流的副本,从而导致保留内存的重复。我建议使用 a StreamReader, aTextWriter并在char缓冲区块中读取流。

In netstandard2.0 System.IO.StreamReaderhas a method ReadBlock

在netstandard2.0System.IO.StreamReader有一个方法读出数据块

you can use this method in order to read the instance of a Stream (a MemoryStream instance as well since Stream is the super of MemoryStream):

您可以使用此方法来读取 Stream 的实例(也是 MemoryStream 实例,因为 Stream 是 MemoryStream 的超类):

private static string ReadStreamInChunks(Stream stream, int chunkLength)
{
    stream.Seek(0, SeekOrigin.Begin);
    string result;
    using(var textWriter = new StringWriter())
    using (var reader = new StreamReader(stream))
    {
        var readChunk = new char[chunkLength];
        int readChunkLength;
        //do while: is useful for the last iteration in case readChunkLength < chunkLength
        do
        {
            readChunkLength = reader.ReadBlock(readChunk, 0, chunkLength);
            textWriter.Write(readChunk,0,readChunkLength);
        } while (readChunkLength > 0);

        result = textWriter.ToString();
    }

    return result;
}

NB. The hazard of memory leak is not fully eradicated, due to the usage of MemoryStream, that can lead to memory leak for large memory stream instance (memoryStreamInstance.Size >85000 bytes). You can use Recyclable Memory stream, in order to avoid LOH. This is the relevant library

注意。内存泄漏的危害并未完全消除,由于使用了MemoryStream,对于大内存流实例(memoryStreamInstance.Size >85000 bytes)可能会导致内存泄漏。您可以使用Recyclable Memory 流,以避免 LOH。这是相关的图书馆