example deserialize c# xml-serialization xmlserializer memorystream

example - deserialize xml string to object c#



Lectura de flujo de memoria a cadena (4)

En el caso de una longitud de flujo muy grande, existe el riesgo de pérdida de memoria debido a Large Object Heap . es decir, el búfer de bytes creado por stream.ToArray crea una copia de la secuencia de memoria en la memoria Heap que conduce a la duplicación de la memoria reservada. Sugeriría usar un StreamReader , un TextWriter y leer la secuencia en trozos de búfers de char .

En netstandard2.0 System.IO.StreamReader tiene un método ReadBlock

puede usar este método para leer la instancia de un Stream (una instancia de MemoryStream también ya que Stream es el super de 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; }

NÓTESE BIEN. El riesgo de pérdida de memoria no está completamente erradicado, debido al uso de MemoryStream, que puede provocar la pérdida de memoria para una instancia de secuencia de memoria grande (memoryStreamInstance.Size> 85000 bytes). Puede usar la secuencia de memoria reciclable para evitar LOH. Esta es la biblioteca relevante

Intento escribir un objeto en una cadena Xml y tomar esa cadena y guardarla en una base de datos. Pero primero necesito obtener la cuerda ...

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

Esto parece funcionar, la secuencia se llena con bytes. Pero cuando vuelvo a leerlo en el búfer y luego en la cadena ... ¡el búfer se llena con ''0''! No estoy seguro de lo que estoy haciendo mal aquí chicos.


Si hubiera verificado los resultados de stream.Read , habría visto que no había leído nada, porque no ha rebobinado la transmisión. (Puede hacer esto con stream.Position = 0; ) Sin embargo, es más fácil simplemente llamar a ToArray :

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

(Necesitarás cambiar el tipo de stream de Stream a MemoryStream , pero está bien ya que está en el mismo método donde la creas).

Alternativamente, e incluso más simplemente, simplemente use StringWriter lugar de StreamWriter . Tendrá que crear una subclase si desea usar UTF-8 en lugar de UTF-16, pero eso es bastante fácil. Vea esta respuesta para un ejemplo.

Me preocupa la forma en que estás atrapando a Exception y asumiendo que significa algo inofensivo, por cierto, sin siquiera registrar nada. Tenga en cuenta que las instrucciones de using generalmente son más limpias que la escritura de bloques explícitos.


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


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