在C#中合并大文件

时间:2020-03-06 14:52:51  来源:igfitidea点击:

我有7-8个xml文件。每个文件的大小约为50 MB。在不获取System.OutOfMemory异常的情况下,在C中以编程方式合并文件的最佳方法是什么?到目前为止,我尝试读取StringBuilder中的每个文件,而不是将其放入字符串生成器数组中,但是我仍然遇到system.outofmemoery异常。有帮助吗?
谢谢,
-尼姆什

解决方案

关于stringbuilder的事情是,我们仍在尝试将所有内容保留在内存中。我们一次只想保留一小部分内存,这意味着使用文件流。不要将整个文件读到内存中,不要在其上打开流,并继续从该流中读取数据。

xml的问题在于我们不能仅将它们彼此添加:我们将破坏标签嵌套。因此,我们需要了解有关xml文件结构的一些知识,以便我们对每个文件边界处的处理方法有所了解。

如果我们有某种理论上可以与StringBuilder一起使用的东西,但是由于内存限制而只能在实践中失败,那么我们应该能够将StringBuilder的.Append()和.AppendLine()方法调用转换为.Write()和.WriteLine()要求一个文件流。

这取决于合并的含义,因为我们尚未发布有关架构的任何信息。

在单个集合中同构简单元素的最简单情况下,我们将直接合并到磁盘上的新文件中,避免进行大量内存工作,从而确保将外部包含的元素剥离并添加到集合周围。

不确定在这种情况下合并意味着什么。我们是指文件的简单串联,还是要检查内容?

例如,

file1.xml

<items>
    <item id="1">
        <name>Widget</name>
    </item>
    <item id="2">
        <name>Widget 2</name>
    </item>
</items>

file2.xml

<items>
    <item id="3">
        <name>Widget</name>
    </item>
    <item id="4">
        <name>Widget 2</name>
    </item>
</items>

可以合并为

<items>
    <item id="1">
        <name>Widget</name>
    </item>
    <item id="2">
        <name>Widget 2</name>
    </item>
</items>
<items>
    <item id="3">
        <name>Widget</name>
    </item>
    <item id="4">
        <name>Widget 2</name>
    </item>
</items>

这是非常琐碎的,或者

<items>
    <item id="1">
        <name>Widget</name>
    </item>
    <item id="2">
        <name>Widget 2</name>
    </item>
    <item id="3">
        <name>Widget</name>
    </item>
    <item id="4">
        <name>Widget 2</name>
    </item>
</items>

鉴于我们正在谈论的数据量,事实并非如此。你是什​​么意思

请定义"合并"。

如果只想串联文件,则使用StreamReader,并逐行读取。

如果我们实际上想产生一个新的有效xml,请使用XmlTextReader。它不会读取内存中的整个文件。

我们需要合并的细节的确至关重要。但是,首先要开始:我们可能希望每个输入文件都使用XmlReader,而输出文件则需要XmlWriter。这样一来,我们就可以流式传输输入和输出。

另一种选择是使用从LINQ到XML的XStreamingElement。我对此没有任何经验,但它可能是使用起来更简单的API。 (LINQ to XML的其余部分肯定比DOM API更好。)

通过调用" copy a.xml + b.xml"命令或者通过" copy"命令使用的Windows文件系统API将它们合并到文件系统中。

就个人而言,当我不得不处理XML文件(通常是受到人身暴力威胁时)时,我会这样做:

  • 通过DataSet.ReadXML()将每个文件加载到.NET DataSet中
  • 合并信息(通过数据集查询)。
  • 通过DataSet.WriteXML()将组合的DataSet写出为XML

然后,我积极删除原始XML文件并擦除磁盘上存在的原始扇区以删除污点。 :-)