c# - Usar MemoryStream para escribir en XML
streamwriter xml c# (6)
He notado dos enfoques diferentes para escribir datos en un archivo XML (el manejo de errores se omite por brevedad).
El primer método es que cree el documento XML y luego simplemente guarde el XML en un archivo:
using (XmlWriter writer = XmlWriter.Create(fileName))
{
writer.WriteStartDocument(true);
writer.WriteStartElement("parentelement");
writer.WriteEndElement();
writer.WriteEndDocument();
}
El segundo método te permite crear un MemoryStream y luego guardar el MemoryStream en un archivo:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
MemoryStream ms = new MemoryStream();
using (XmlWriter writer = XmlWriter.Create(ms, settings))
{
writer.WriteStartDocument(true);
writer.WriteStartElement("parentelement");
writer.WriteEndElement();
writer.WriteEndDocument();
}
using (FileStream fs = File.Open(fileName, FileMode.Create, FileAccess.Write))
{
ms.WriteTo(fs);
ms.Dispose();
}
Supongo que la lógica para usar MemoryStream es garantizar que el archivo XML se pueda generar antes de intentar guardar el archivo. ¿El método MemoryStream proporcionará un evento de escritura atómica y / o protegerá contra problemas de escritura mientras agrega entradas al archivo XML?
¿Alguien puede explicar si esto es realmente necesario o simplemente una forma exagerada de agregar líneas innecesarias de código a mi proyecto?
Esto es excesivo y un desperdicio.
Los dos enfoques clave se basan en
- No conoce la estructura completa del documento hasta el final.
- Cuando "crea" las partes del documento, sabe que son la forma final de esta parte del documento.
el primero requiere la creación de un modelo en memoria del documento (para el cual está diseñado el modelo DOM). Una vez que haya terminado, simplemente escribir directamente en la secuencia de archivos está bien.
El segundo le permite ahorrar memoria y complejidad considerables y simplemente usar XmlWriter que puede apuntar directamente a la secuencia final (en este caso, una secuencia de archivos).
En ningún momento es necesario usar un MemoryStream
La versión de MemoryStream
es un desperdicio en esta ocasión. MemoryStream
es útil si desea realizar un trabajo similar a Stream
, pero no desea un archivo real. Si está escribiendo un archivo, simplemente escriba en el archivo. Esto evita la necesidad de almacenar todos los datos en la memoria.
No tiene que usar un MemoryStream para usar el XmlWriter. El XmlWriter puede escribir directamente en un archivo; puede usar otra sobrecarga del método XmlWriter.Create, que toma un nombre de archivo como argumento, o en lugar de escribir en un MemoryStream, también puede escribir en un XmlTextWriter o un FileStream.
Entonces, tu 2nd codenippet podría escribirse como:
using( FileStream fs = ... )
{
XmlWriter writer = XmlWriter.Create (fs);
}
AFAIK, el XmlWriter no lo protegerá de crear un Xml no bien formado.
Si usted (por algún motivo) desea asegurarse de que XmlWriter tiene éxito (es decir, el archivo puede estar truncado, pero en la mayoría de los casos esto se debe a, como se mencionó, no cerrar las etiquetas), puede usar un archivo temporal, fx algo similar a esto:
public class TempFileStream : FileStream
{
public TempFileStream(Action<string> onClose)
: base(Path.GetTempFileName(), FileMode.OpenOrCreate, FileAccess.ReadWrite)
{
this.CloseDelegate = onClose;
}
protected Action<string> CloseDelegate
{
get;
set;
}
public override void Close()
{
base.Close();
if (File.Exists(this.Name))
{
this.CloseDelegate(this.Name);
}
}
}
El usado como:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
using (TempFileStream tfs = new TempFileStream(f => File.Move(f, filename))
using (XmlWriter writer = XmlWriter.Create(tfs, settings))
{
writer.WriteStartDocument(true);
writer.WriteStartElement("parentelement");
writer.WriteEndElement();
writer.WriteEndDocument();
}
Esto no consumirá mucha memoria (por supuesto, solo tiene / tiene más sentido cuando el XML resultante es grande)
Es cierto que el enfoque de flujo de memoria es un desperdicio para operaciones simples, pero es muy útil para casos como guardar el XML como archivo cifrado, como archivo comprimido, etc.
Creo que usar una secuencia de memoria sería útil si crea el documento en una aplicación web o servicio web. La ubicación del archivo puede entrar en conflicto con otro proceso que podría estar ejecutando el mismo proceso que podría causar resultados no válidos. En una secuencia de memoria, el procesamiento debe segregarse.