如何有效地使用内存在C#中附加大型XML文件

时间:2012-08-03 15:50:49

标签: c# xml memory-management file-io xmlwriter

我是否有某种方法可以合并两个XmlDocuments而不将第一个保存在内存中?

我必须遍历一个包含多达一百个(~300MB)XML文件的列表,每个最多连接1000个节点,重复整个过程多次(因为清除新节点列表以节省内存)。目前,我在添加新节点之前将整个XmlDocument加载到内存中,这些节点目前尚未成立。

你会说最好的方法是什么?我有一些想法,但我不确定哪个是最好的:

  1. 从不加载整个XMLDocument,而是同时使用XmlReaderXmlWriter来写入随后重命名的临时文件。
  2. 仅为新节点创建XmlDocument,然后手动将其写入现有文件(即file.WriteLine( "<node>\n" )
  3. 别的什么?
  4. 非常感谢任何帮助。

    修改更多细节可以回答一些评论:

    程序将几个大型日志解析为XML,按源分组到不同的文件中。它只需要每天运行一次,一旦编写了XML,就会有一个轻量级的专有读取器程序,它提供有关数据的报告。程序只需要每天运行一次,因此可能很慢,但是在执行其他操作的服务器上运行,主要是文件压缩和传输,这不会受到太大影响。

    数据库可能会更容易,但公司不会很快这么做!

    按原样,程序最多使用几GB内存在dev机器上运行,但在服务器上运行时会抛出内存异常。

    最终修改 这项任务非常低,这就是为什么只需要额外的费用就可以获得一个数据库(虽然我会考虑使用mongo)。

    该文件只会附加到,并且不会无限增长 - 每个最终文件仅用于一天的日志,然后在第二天生成新文件。

    我可能会使用XmlReader / Writer方法,因为它最容易确保XML有效性,但我已经考虑了所有的评论/答案。我知道拥有这么大的XML文件并不是一个特别好的解决方案,但这是我所限制的,所以感谢所有给予的帮助。

1 个答案:

答案 0 :(得分: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标头,可能是文档元素或其他一些不必要的结构。你可以通过逐行解析文件来做到这一点