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...
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.
This question is related to
c#
xml-serialization
xmlserializer
memorystream
string result = System.Text.Encoding.UTF8.GetString(fs.ToArray());
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 TextWriter
and read the stream in chunks of char
buffers.
In netstandard2.0 System.IO.StreamReader
has a method ReadBlock
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):
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
string result = Encoding.UTF8.GetString((stream as MemoryStream).ToArray());
Source: Stackoverflow.com