2016-10-22 54 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許可證)。