如何比较两个大的CSV文件并获得差异文件

本文关键字:文件 CSV 两个 何比较 比较 | 更新日期: 2023-09-27 17:53:16

我需要逐行比较2个csv(巨大的文件),并在一个单独的文件中写入差异行。一个文件中的行可以出现在另一个文件中的任何位置。我需要比较整个行。指针吗?

如何比较两个大的CSV文件并获得差异文件

一种常见的方法是为一个文件(最好是较小的那个)中的每一行计算哈希码。然后将整个文件放入散列表中。这将是较小文件的索引。

之后,遍历较大的文件。为每一行计算它的哈希值。然后查看索引。如果没有这样的散列码,那么这一行就是差值。否则,如果存在这样的散列代码(可能不止一行具有相同的散列),则将源行与散列表中所有冲突的行进行完整比较,并查看是否存在重复。

现在,如果没有重复,那么源文件中的行再次是唯一的,并将其推送到输出。

否则,如果存在重复,您可能希望从哈希表中删除该重复并跳过输入行。这意味着两个文件中的两行已被检测为相等,并将相互取消。

遍历完较大的文件后,需要决定如何处理散列表中的其余行。您可能也想把它们全部推到输出中,因为这些行是另一个文件中不存在的。

现在我试着概括一下伪代码:

dict = new dictionary<code, list<row>>
-- Indexing phase
foreach row in file1
    code = hash(row)
    if dict.contains(code) then
        dict[hash].add(row)
    else
        dict[hash] = new list(row)
-- Comparison phase
foreach row in file2
    code = hash(row)
    bool unique = true
    if dict.contains(code) then
        foreach indexedRow in dict[code]
            if indexedRow is the same as row then
                begin
                    unique = false
                    remove indexedRow from dict[code]
                end
    if unique then
        push row to output
-- Finalization phase
foreach row in dict
    push row to output

此解决方案的最大优点是其运行时复杂度为O(M + N),其中M和N是每个文件中的行数。它的缺点是为索引占用O(min(M, N))内存

又快又脏:

private void DoSomething()
{
  var lines1 = File.ReadAllLines(@"file1.csv");
  var lines2 = File.ReadAllLines(@"file2.csv");
  var diff1From2 = FindDifferences(lines1, lines2);
  var diff2From1 = FindDifferences(lines2, lines1);
  var diffs = new List<string>(diff1From2);
  diffs.AddRange(diff2From1);
  File.WriteAllLines(@"file3.csv", diffs);
}
private static string[] FindDifferences(string[] linesFirst, string[] linesSecond)
{
  return (from line1 in linesFirst
    let isLineEqual = linesSecond.Any(line2 => line1 == line2)
    where isLineEqual == false
    select line1).ToArray();
}