使用大文件将文本从一个文件附加到另一个文件的最快方法是什么

What's the fastest way of appending text from one file to another with huge files

提问人:JohnA 提问时间:3/20/2022 更新时间:3/21/2022 访问量:267

问:

因此,我有 5 个文本文件,每个 50GB,我想将它们全部合并为 1 个文本文件,然后调用 LINQ 语句,以便新文件中只有唯一的条目。.Distinct()

我现在的做法是这样的

foreach (var file in files)
{
    if (Path.GetExtension(file) == ".txt")
    {
        var lines = File.ReadAllLines(file);
        var b = lines.Distinct();
        File.AppendAllLines(clear, lines);
        
    }
}

这里出现的问题是应用程序现在将整个文本文件加载到内存中,使我的 RAM 使用率高达 100%。如果我有 64GB 的内存,这个解决方案可能会起作用,但我只有 16GB。对我来说,实现我想要完成的目标的最佳选择是什么?我应该利用 CPU 上的内核吗?运行 5900x。

C# .NET IO RAM 文件.ReadAllLines

评论

0赞 emoacht 3/20/2022
一行应该在一个文件中还是所有文件中是不同的?
0赞 JohnA 3/20/2022
我正在尝试使最终文件只有不同的条目
0赞 Ibram Reda 3/20/2022
为了节省内存,您应该将文件作为流读取附加到另一个流
0赞 Klaus Gütter 3/20/2022
逐行读取输入文件,并逐行写入输出文件。棘手的部分是 Distinct。你根本无法记住记忆中所有看到的台词。在这里找到解决方案:线路平均有多长?存在多少(百分比)重复项?
0赞 JohnA 3/20/2022
@KlausGütter 我想说的是,这些行的平均长度约为 15 个字符

答:

1赞 Mark Cilia Vincenti 3/21/2022 #1

如果维持秩序并不重要,并且如果潜在的字符是有限的(例如A-Z),那么可能会说,“好吧,让我们从As开始”。

因此,您从每个文件开始,然后逐行浏览,直到找到以“A”开头的行。如果找到一个,请将其添加到新文件和 HashSet 中。每次找到以“A”开头的新行时,请检查它是否在 HashSet 中,如果没有,请将其添加到新文件和 HashSet 中。处理完所有文件后,释放 HashSet 并跳到下一个字母 (B)。

您将以这种方式遍历文件 26 次。

当然,您可以进一步优化它。检查有多少可用内存,并将可能的字符除以范围,例如,在第一次迭代中,您的 HashSet 可能包含以 A-D 开头的任何内容。