Использование 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 как зашифрованный файл, как сжатый файл и т. д.


Это перебор и расточительство.

два ключевых подхода на основе

  1. вы не знаете полную структуру документа до конца.
  2. когда вы "создаете" части документа, вы знаете, что они являются окончательной формой этой части документа.

первый требует создания модели в памяти документа (для которой предназначена модель 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.