8

我注意到将数据写入 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 文件。当您将条目添加到 XML 文件中时,MemoryStream 方法是否会提供原子写入事件和/或防止写入问题?

谁能解释这是否真的有必要,或者只是一种在我的项目中添加不必要的代码行的矫枉过正的方式?

4

6 回答 6

15

在这种情况下,MemoryStream版本是浪费的。MemoryStream如果您想执行Stream类似的工作,但不想要实际文件,这很有用。如果您正在写入文件,则只需写入文件即可。这避免了在内存中缓冲所有数据的需要。

于 2009-01-28T08:21:21.747 回答
3

确实,内存流方法对于简单的操作来说是浪费的,但它对于将 xml 保存为加密文件、压缩文件等情况非常有用。

于 2009-11-01T16:17:38.273 回答
2

这是矫枉过正和浪费。

两种关键方法基于

  1. 直到最后,您才知道文档的完整结构。
  2. 当您“创建”文档的各个部分时,您知道它们是文档这一部分的最终形式。

第一个需要创建文档的内存模型(为其设计了 DOM 模型)。完成后,只需直接写入文件流即可。

第二个允许您节省大量内存和复杂性,并且只需使用可以直接指向结束流(在本例中为文件流)的XmlWriter 。

在任何阶段都没有必要使用 MemoryStream

于 2009-01-28T08:23:40.400 回答
1

如果您(出于某种原因)想要确保 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 很大时才有意义/更有意义)

于 2009-01-28T10:43:32.443 回答
1

我认为如果在 Web 应用程序或 Web 服务中创建文档,使用内存流会很有用。文件位置可能与可能正在运行相同处理的另一个进程冲突,这可能会导致无效结果。在内存流中,处理应该是分开的。

于 2010-02-01T22:54:08.003 回答
0

您不必使用 MemoryStream 来使用 XmlWriter。XmlWriter 可以直接写入文件;您可以使用 XmlWriter.Create 方法的另一个重载,它将文件名作为参数,或者您也可以写入 XmlTextWriter 或 FileStream,而不是写入 MemoryStream。

所以,你的第二个代码片段可以写成:

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

AFAIK,XmlWriter 不会保护您免于创建格式不正确的 Xml。

于 2009-01-28T08:15:49.433 回答