Использование 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 обеспечивать атомарное событие записи и / или защищать от проблем записи при добавлении записей в XML-файл?
может ли кто-нибудь объяснить, действительно ли это необходимо или просто излишний способ добавить ненужные строки кода в мой проект?
6 ответов
на MemoryStream
версия расточительна по этому поводу. MemoryStream
полезна, если вы хотите выполнить Stream
- как работа, но не нужен фактический файл. Если ты ... --4-- > are написание файла, затем просто напишите в файл. Это позволяет избежать необходимости буферизации всех данных в памяти.
Это правда, что подход потока памяти расточителен для простых операций, но он очень полезен для таких случаев, как сохранение xml как зашифрованный файл, как сжатый файл и т. д.
Это перебор и расточительство.
два ключевых подхода на основе
- вы не знаете полную структуру документа до конца.
- когда вы "создаете" части документа, вы знаете, что они являются окончательной формой этой части документа.
первый требует создания модели в памяти документа (для которой предназначена модель DOM). Как только вы закончите с этим, просто пишу непосредственно к файловому потоку все в порядке.
второй позволяет сэкономить значительную память и сложность и просто использовать XmlWriter который может указывать непосредственно на конечный поток (в данном случае поток файлов).
ни на каком этапе не нужно использовать MemoryStream
Если вы (по какой - то причине) хотите обеспечить успех XmlWriter (т. е. в противном случае файл может быть усечен, но в большинстве случаев это будет связано с - как уже упоминалось-не закрывающими тегами), вы можете использовать временный поток файлов, fx что-то подобное этому:
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.
Итак, вы 2-й codesnippet можно записать как:
using( FileStream fs = ... )
{
XmlWriter writer = XmlWriter.Create (fs);
}
AFAIK, XmlWriter не защитит вас от создания плохо сформированного Xml.