我有两个大的(比如300,000 * 100)矩形csv文件,它们具有相同数量的相应行和列。我需要找到2个文件中每个相应单元格之间的差异。 程序应该o / p不同的行和单元格号以及不同的内容。
由于行数/列数非常大,我正在寻找最有效的方法。
最初我开始使用awk进行探索,而this看起来很有希望,但我之前没有使用过awk并且没有成功将其扩展到100列而不是2,如示例中所示
接下来,我尝试了一种使用Java的强力方法 - 将文件加载到2个2-D阵列中。初始化100个线程,每个线程在给定列上工作,当找到差异时,每个线程将行,单元格和diff值放入HashMap(列号为Key)。我确实尝试通过比较同时将第二个文件读入数组来进行优化,但实际上因为我正在访问每个单元格,所以没有办法可以很快(完成比较需要近8个小时)
我对awk或Java都没关系。并且对任何其他完全不同的方法开放。
答案 0 :(得分: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)}'
打印&#34;行#列#left right&#34;不等的细胞的价值。
如果除了行号之外还要打印键列,可以轻松添加
$ 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)}'
答案 1 :(得分: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并在有差异的行上进行循环,而不是所有行。
答案 2 :(得分: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许可证)。