如何在C#中高效地使用内存向大型XML文件追加内容

5
有没有一种方法可以在不将第一个XmlDocument保存在内存中的情况下将两个XmlDocuments合并?
我必须循环遍历多达一百个大约300MB的XML文件列表,向每个文件追加多达1000个节点,并重复整个过程几次(因为新节点列表被清除以节省内存)。目前,在添加新节点之前,我将整个XmlDocument加载到内存中,这是不可行的。
您认为最好的方法是什么?我有一些想法,但不确定哪种最好:
1.永远不要加载整个XMLDocument,而是同时使用XmlReader和XmlWriter写入临时文件,然后将其重命名。
2.只为新节点创建XmlDocument,然后手动将其写入现有文件(即file.WriteLine("<node>\n"))。
3.其他方法?
任何帮助都将不胜感激。
编辑:根据一些评论中的答案提供更多细节:
该程序将几个大型日志解析为XML,并按源分组到不同文件中。它只需要每天运行一次,一旦编写了XML,就有一个轻量级专有读取器程序,可以对数据进行报告。该程序只需要每天运行一次,因此可以很慢,但是在执行其他操作(主要是文件压缩和传输)的服务器上运行,这些操作不能太多地影响。
数据库可能会更容易,但公司不会很快这样做!
目前,该程序在dev机器上运行时使用的内存不超过几GB,但在服务器上运行时会抛出内存不足异常。
最终编辑: 任务相当低优先级,这就是为什么只要花费额外的费用才能获得数据库(尽管我会研究mongo)。
文件将仅被附加,并且不会无限增长-每个最终文件仅用于一天的日志,然后在第二天生成新文件。
我可能会使用XmlReader / Writer方法,因为它最容易确保XML有效性,但我已经考虑了您所有的评论/答案。我知道拥有如此大的XML文件不是特别好的解决方案,但这是我所限制的,所以感谢提供的所有帮助。

2
我认为第一种方式是可行的,但我没有处理大文件的实际经验。 - Jeff Mercado
这个编程项目的最终目标是什么,也就是说它的成果是什么? - HatSoft
1
你能提供一些关于这个问题的更多背景吗?也许切换到数据库是一个更好的解决方案。 - eabraham
1
我建议对大多数文件操作使用临时文件,如果操作成功,则使用File.Replace将旧文件替换为临时文件。这样可以在操作过程中出现任何问题时保存您的数据。 - Dour High Arch
1
如果数据集很大(并且假设您不能使用数据库),那么二进制文件不是更好吗?没有必要将所有数据作为文本读入内存;在完成更新后将其转储到XML中。更好的方法是,为什么不使用Mongo DB(无需安装,只需下载二进制文件,与C#集成良好)?使用文本表示如此大的数据集似乎有些疯狂。 - McGarnagle
显示剩余6条评论
1个回答

2

如果您希望完全确定XML结构,使用XMLWriter和XMLReader是最好的选择。

然而,为了获得绝对最高的性能,你可以使用直接字符串函数快速重新创建此代码。虽然您可以这样做,但您将失去验证XML结构的能力 - 如果一个文件出现错误,您将无法纠正它:

using (StreamWriter sw = new StreamWriter("out.xml")) {
    foreach (string filename in files) {
        sw.Write(String.Format(@"<inputfile name=""{0}"">", filename));
        using (StreamReader sr = new StreamReader(filename)) {
            // Using .NET 4's CopyTo(); alternatively try http://bit.ly/RiovFX
            if (max_performance) {
                sr.CopyTo(sw);
            } else {
                string line = sr.ReadLine();
                // parse the line and make any modifications you want
                sw.Write(line);
                sw.Write("\n");
            }
        }
        sw.Write("</inputfile>");
    }
}

根据您输入的XML文件的结构,您可能选择删除XML头、文档元素或其他一些不必要的结构。您可以通过逐行解析文件来完成这个过程。


感谢提供CopyStream链接 - 即使我现在不使用它,我相信将来一定会有用! - Overlord_Dave
我真是太傻了 - 我忘记了.NET 4中的CopyTo方法 - 解释在这里http://msdn.microsoft.com/en-us/library/dd782932.aspx。现在已经内置了。 - Ted Spence

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