2016-10-22 82 views
1

我有两个大的(比方说300,000 * 100)矩形csv文件,它们具有相同数量的相应行和列。我需要找出2个文件中每个对应单元之间的差异。 程序应该对不同的行和单元格号和不同的内容。查找2个csv文件差异的有效方法

由于行/列的数量非常大,我正在寻找最有效的方法来做到这一点。

起初,我开始使用awk探索和this看起来前途无量,但我还没有使用awk前工作,在此延伸至100列,而不是2作为例子

接下来不成功,我尝试了使用Java的一种强力方法 - 将文件加载到2个二维数组中。初始化100个线程,每个线程工作在给定的列上,当发现差异时,每个线程将行,单元格和差异值放入HashMap(列号为Key)。我试图通过比较读取第二个文件到阵列中来进行优化,但实际上,由于我正在访问每个单元,因此无法快速完成比较(花费将近8小时来完成比较)。

I'可以使用awk或Java。并开放给任何其他完全不同的方法。

+1

只需使用'diff'来检查文件的差异呢?输出可以存储在一个文件中或用于脚本进一步分析并采取适当的行动。 –

+0

这正是当前程序正在做的。 diff只是打印整个行,并且在很多情况下,从左边的文件中说出10行,然后在右边的文件中跟着10行。所以人们必须手动复制成excel,并在视觉上比较每一列。请注意,90%的行有一些区别..所以diff o/p是相当大的 – Plaiska

+2

那么让excel解决它呢?没有充分加快它的功能,但我相信一些矩阵搜索可以应用到多个选项卡,也许更改背景颜色? –

回答

3

awk来救援!

这是一个没有脑子为此在awk

$ paste -d, file.1 file.2 | 
    awk -F, '{m=NF/2; for(i=1;i<=m;i++) if($i!=$(i+m)) print NR,i,$i,$(i+m)}' 

打印“行号列#左,右”不平等的细胞的值。

如果你要打印除了行号键列,您可以轻松地将其添加

$ paste -d, file.1 file.2 | 
    awk -F, -v key=8 '{m=NF/2; 
        for(i=1;i<=m;i++) 
         if($i!=$(i+m)) print $key,NR,i,$i,$(i+m)}' 
+0

在输出中是否可以输出固定列的值(比如说第8列的值)?这个特定的值保证与它的行的唯一密钥相同 – Plaiska

+0

如果你用你的文件试试这个,请发布时间,它不应该超过一分钟左右。 – karakfa

+0

真棒..花了大约1.5分钟完成。当然,Java版本有额外的输出,但由于缓慢而无用。将接受这个答案。我应该能够进一步处理o/p以获得我需要的东西。谢谢 – Plaiska

1

要考虑的事情:

$ cat file1 
1,2,aa 
1,2,3 
1,bb,3 
1,2,3 

$ cat file2 
1,2,cc 
1,2,3 
1,dd,3 
1,2,3 

$ diff file1 file2 | 
awk -F, ' 
    /^[0-9]/ { row=$0+0; next } 
    sub(/^< /,"") { split($0,a); next } 
    sub(/^> /,"") { for (col=1;col<=NF;col++) if ($col != a[col]) print row, col, a[col], $col } 
' 
1 3 aa cc 
3 2 bb dd 

这应该是非常快的,因为它只执行awk并在有差异的行上执行循环,而不是所有行。

1

univocity-parsers“CSV解析器不会需要更长的时间超过5秒来处理这个:

public void diff(File leftInput, File rightInput) { 
    CsvParserSettings settings = new CsvParserSettings(); //many config options here, check the tutorial 

    CsvParser leftParser = new CsvParser(settings); 
    CsvParser rightParser = new CsvParser(settings); 

    leftParser.beginParsing(leftInput); 
    rightParser.beginParsing(rightInput); 

    String[] left; 
    String[] right; 

    int row = 0; 
    while ((left = leftParser.parseNext()) != null && (right = rightParser.parseNext()) != null) { 
     row++; 
     if (!Arrays.equals(left, right)) { 
      System.out.println(row + ":\t" + Arrays.toString(left) + " != " + Arrays.toString(right)); 
     } 
    } 

    leftParser.stopParsing(); 
    rightParser.stopParsing(); 
} 

披露:我是这个库的作者。它是开放源代码和免费的(Apache V2.0许可证)。