【问题标题】:How to write (big) XML to a file in C#?如何将(大)XML 写入 C# 中的文件?
【发布时间】:2010-10-26 16:48:45
【问题描述】:

伙计们,

请问,在 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 文档,其架构不指定任何命名空间...即:只有默认命名空间,一切都在其中。

我的经验:我几乎是 C# 和 .NET 新手。我已经用各种语言编程了大约 10 年,包括 Java、VB、C 和一些 C++。

大家干杯。基思。

PS:现在是晚餐时间,所以我会离开大约半小时。

【问题讨论】:

    标签: c# xml


    【解决方案1】:

    对于编写大型 xml,XmlWriter(直接)是你的朋友——但它更难使用。另一种选择是使用 DOM/对象模型方法并将它们组合起来,这可能是可行的...

    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 };
            }
        }
    }
    

    【讨论】:

    • 马克,谢谢。 (根据我对大卫施密特回答的评论)我会尝试两种方式并运行一些性能测试。先生,我感谢您周到的回答以及示例代码。惊人的。塔。 ;-) 我只希望有一天我能报答这个人情。干杯。基思。
    【解决方案2】:

    使用XmlWriter

    [...] 一个提供快速、 非缓存,只进的方式 生成包含的流或文件 XML 数据。

    【讨论】:

    • 好的,我将在原型中尝试两种方式(仅针对关键元素,以节省时间)。 XmlWriter 看起来像是“正确的答案”,但我想它会比我最初的 XmlSerializer 解决方案涉及更多的代码,并且还会抵消使用生成的绑定类的“灵活性”优势......因为手工编写的代码必须知道所有关于确切的架构。我感谢你的时间......干杯。基思。
    【解决方案3】:

    您是否考虑过在将其写入磁盘之前对其进行压缩?使用 XML,您可以达到 10 倍以上的压缩率,甚至更多。与读取整个 500Mb 版本相比,压缩文件和编写压缩版本所需的时间可能更少。

    【讨论】:

    • 更大的问题是内存中的 DOM 表示通常是实际底层 xml 的 > x10 ......而且 5Gb 太大而无法合理处理。同样,如果存在未压缩文件的现有 API/预期,它也无济于事。
    • 这是个好主意。谢谢你。我还不如在它撞到磁盘之前压缩它;节省一些时间(和内存)读取它并将其作为 HttpWebRequest 发送。我们对这种 XML 的体验是压缩到其展开后大小的大约四分之一...节省 (3/4) * 500 = 375 MB RAM。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-31
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 2018-07-26
    • 2014-03-20
    • 1970-01-01
    相关资源
    最近更新 更多