Использование MemoryStream для записи в XML - PullRequest
8 голосов
/ 28 января 2009

Я заметил два разных подхода к записи данных в файл 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 ]

15 голосов
/ 28 января 2009

В этом случае версия MemoryStream расточительна. MemoryStream полезно, если вы хотите выполнить Stream -подобную работу, но не хотите иметь настоящий файл. Если вы пишете файл, просто напишите в файл. Это позволяет избежать необходимости буферизовать все данные в памяти.

3 голосов
/ 01 ноября 2009

Это правда, что подход с использованием потока памяти бесполезен для простых операций, но он очень полезен для таких случаев, как сохранение XML-файла как зашифрованного файла, сжатого файла и т. Д.

2 голосов
/ 28 января 2009

Это лишнее и ненужное.

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

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

первый требует создания модели документа в памяти (для которой предназначена модель DOM). Как только вы закончите с этим, просто пишите прямо в поток файлов.

Второй позволяет вам сэкономить значительную память и сложность и просто использовать XmlWriter , который может указывать непосредственно на конечный поток (в данном случае поток файлов).

Ни на каком этапе нет необходимости использовать MemoryStream

1 голос
/ 02 февраля 2010

Я думаю, что использование потока памяти было бы полезно при создании документа в веб-приложении или веб-сервисе. Расположение файла может конфликтовать с другим процессом, который может выполнять ту же обработку, что может привести к недопустимым результатам. В потоке памяти обработка должна быть разделена.

1 голос
/ 28 января 2009

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

0 голосов
/ 28 января 2009

Вам не нужно использовать MemoryStream для использования XmlWriter. XmlWriter может напрямую записывать в файл; вы можете использовать другую перегрузку метода XmlWriter.Create, который принимает имя файла в качестве аргумента, или вместо записи в MemoryStream вы также можете записать в XmlTextWriter или FileStream.

Итак, ваш 2-й кодсниппет может быть записан как:

using( FileStream fs = ... )
{
    XmlWriter writer = XmlWriter.Create (fs);
}

AFAIK, XmlWriter не защитит вас от создания некорректного Xml.

...