如何在C#中将(大型)XML写入文件?

13

大家好,

请问在C# .NET 3.5中如何高效地编写非常大的XML文档(最多达500 MB)?我已经搜索了一下,似乎没有找到针对这个特定问题的解决方案。

我的先前帖子(What is the best way to parse (big) XML in C# Code?)涵盖了读取类似大小的XML文档的内容...现在我需要考虑如何将更新功能(http://www.opengeospatial.org/standards/sfa)写入“update.xml”文档。

我的想法:显然,由于要生成的文档的最大大小,使用一个大型DOM是行不通的。我正在使用XSD.EXE从架构生成绑定类......这与XmlSerializer类很好地配合使用,但我认为它在“底层”构建了一个DOM。这是正确的吗?我无法一次将所有功能(多达50,000个)保存在内存中。我需要从数据库中读取一个功能,对其进行序列化,然后将其写入文件。所以我想应该使用XmlSerializer将每个单独的功能写入文件的“doclet”。我目前还不知道这是否可能/可行。

你怎么看?

背景:我正在将旧的VB6 MapInfo“客户端插件”移植到C#。有一个现有的J2EE“更新服务”(实际上只是一个Web应用程序),该程序(以及其他程序)必须使用。我不能更改服务器,除非绝对必要;特别是如果要更改其他客户端。服务器接受具有架构的XML文档,该架构未指定任何命名空间......即仅存在默认命名空间,并且所有内容都在其中。

我的经验:我在各种编程语言中编程已有大约10年的时间,包括Java、VB、C以及一些C++。但对于C#和.NET还是比较陌生的新手。

祝大家好运。Keith。

附言:现在是晚饭时间,我会离开大约半个小时。

3个回答

16

如果要编写大型XML文件,XmlWriter(直接使用)是您的良友,但它更难使用。另一种选择是使用DOM /对象模型方法并将它们结合起来,这可能是可行的,如果您掌控 XmlWriterSettings 并禁用xml标记,并且摆脱命名空间声明...

<code>using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;    
public class Foo {
    [XmlAttribute]
    public int Id { get; set; }
    public string Bar { get; set; }
}
static class Program {
    [STAThread]
    static void Main() {
        using (XmlWriter xw = XmlWriter.Create("out.xml")) {
            xw.WriteStartElement("xml");
            XmlSerializer ser = new XmlSerializer(typeof(Foo));
            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
            ns.Add("","");
            foreach (Foo foo in FooGenerator()) {
                ser.Serialize(xw, foo, ns);
            }
            xw.WriteEndElement();
        }
    }    
    // streaming approach; only have the smallest amount of program
    // data in memory at once - in this case, only a single `Foo` is
    // ever in use at a time
    static IEnumerable<Foo> FooGenerator() {
        for (int i = 0; i < 40; i++) {
            yield return new Foo { Id = i, Bar = "Foo " + i };
        }
    }
}
</code>

Marc,谢谢。 (根据我对David Schmitt答案的评论)我会尝试两种方法并运行一些性能测试。感谢您先生提供的周到答案和示例代码。太棒了。谢啦。;-)我只希望有朝一日能回报您的恩情。干杯。Keith. - corlettk

9

使用XmlWriter

[...]它是一种提供快速、非缓存、单向生成包含XML数据的流或文件的编写器。


好的,我会在原型中尝试两种方法(仅针对关键元素,以节省时间)。XmlWriter看起来像是“正确的答案”,但我猜它将涉及比我最初的XmlSerializer解决方案更多的代码,并且还会使使用生成的绑定类的“灵活性”受到影响...因为手写代码必须了解确切的模式。感谢您的时间...祝好。Keith. - corlettk

1
你有没有考虑在将其写入磁盘之前进行压缩?使用 XML,您可以达到超过10倍的压缩比甚至更多。压缩文件和写入压缩版本可能需要的时间比读取整个500MB版本要少。

1
更大的问题是内存中的DOM表示通常比实际的底层xml大10倍以上...而且5GB太大了,无法合理处理。如果存在未压缩文件的现有API/期望,这也没有帮助。 - Marc Gravell
这是一个很好的想法。谢谢你。在它被写入磁盘之前,我可以将其压缩,以节省读取和发送HttpWebRequest所需的时间(和内存)。我们使用压缩后的XML的经验表明,它的大小只有原来的四分之一... 节省了(3/4)* 500 = 375 MB的RAM。 - corlettk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接