Использование MemoryStream для записи в XML
Я заметил два разных подхода к записи данных в файл XML (обработка ошибок для краткости опущена).
Первый способ заключается в создании XML-документа, а затем просто сохранении XML в файл:
using (XmlWriter writer = XmlWriter.Create(fileName))
{
writer.WriteStartDocument(true);
writer.WriteStartElement("parentelement");
writer.WriteEndElement();
writer.WriteEndDocument();
}
Во втором методе вы создаете MemoryStream, а затем сохраняете MemoryStream в файл:
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();
}
Я предполагаю, что логика использования MemoryStream заключается в том, чтобы гарантировать, что файл XML может быть собран перед попыткой сохранить файл. Будет ли метод MemoryStream обеспечивать событие записи Atomic и / или защищать от проблем записи при добавлении записей в файл XML?
Может кто-нибудь объяснить, если это действительно необходимо, или просто излишний способ добавить ненужные строки кода в мой проект?
6 ответов
MemoryStream
Версия по этому поводу расточительна. MemoryStream
полезно, если вы хотите выполнить Stream
как работа, но не хочу фактического файла. Если вы пишете файл, просто напишите в файл. Это позволяет избежать необходимости буферизовать все данные в памяти.
Это правда, что подход с использованием потока памяти является расточительным для простых операций, но он очень полезен для таких случаев, как сохранение XML-файла в виде зашифрованного файла, в виде сжатого файла и т. Д.
Это излишество и пустая трата времени.
Два ключевых подхода основаны на
- Вы не знаете всю структуру документа до конца.
- Когда вы "создаете" части документа, вы знаете, что они являются окончательной формой этой части документа.
первый требует создания модели документа в памяти (для которой предназначена модель DOM). Как только вы закончите с этим, просто пишите прямо в поток файлов.
Второй позволяет вам сэкономить значительную память и сложность и просто использовать XmlWriter, который может указывать непосредственно на конечный поток (в данном случае файловый поток).
Ни на каком этапе нет необходимости использовать MemoryStream
Если вы (по какой-то причине) хотите обеспечить успешное выполнение XmlWriter (т. Е. В противном случае файл может быть обрезан, но в большинстве случаев это будет связано с - как уже упоминалось - не с закрытием тегов), вы можете использовать временный файловый поток, например нечто похожее к этому:
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);
}
}
}
Используется как:
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();
}
Это не будет занимать много памяти (конечно, это имеет смысл только тогда, когда получающийся XML большой)
Я думаю, что использование потока памяти было бы полезно при создании документа в веб-приложении или веб-сервисе. Расположение файла может конфликтовать с другим процессом, который может выполнять ту же обработку, что может привести к неверным результатам. В потоке памяти обработка должна быть разделена.
Вам не нужно использовать MemoryStream для использования XmlWriter. XmlWriter может напрямую записывать в файл; вы можете использовать другую перегрузку метода XmlWriter.Create, который принимает имя файла в качестве аргумента, или вместо записи в MemoryStream вы также можете записать в XmlTextWriter или FileStream.
Итак, ваш второй кодекснипет может быть записан как:
using( FileStream fs = ... )
{
XmlWriter writer = XmlWriter.Create (fs);
}
AFAIK, XmlWriter не защитит вас от создания плохо сформированного Xml.