2013-05-03 63 views
0

修改大文件I有一個文件閱讀比較和用java

base.txt 
5071111111 
5071111112 
5071111113 
5071111114 
..... around 15 lakh numbers 

和另一個文件

status.txt 
5071111112,sended 
5071111113,failed 
..... 

實際的情況是,我有基本文件包含移動電話號碼,用於發送消息和其他文件 包含存儲在status.txt中的每個號碼的消息狀態。

現在我的任務就是合併兩個文件,並保持普通文件一樣

merged.txt 
5071111111 
5071111112,sended 
5071111113,failed 
5071111114 
....... and so on 

我想通常的解決辦法採取一個數量從status.txt中即「5071111112,sended」,並比較base.txt 和如果未找到號碼,則將該號碼複製到merged.txt中,如果找到號碼,則將該號碼的更新後的內容複製到merged.txt中。

現在merged.txt將作爲我的基礎文件。

此外,status.txt文件定期進入,所以比較和創建新的merging.txt文件以及刪除以前的文件並重新命名新文件的過程依此類推。

我也嘗試過的RandomAccessFile類,但我面對數據截斷問題的相似之處在於這裏所描述的問題, link

我讀張貼#2,但許多人都建議我上面提到的方式幾個答案。 我們有其他解決方案嗎?

+0

數字是否保證在文件中排序? (因爲他們中的例子) – FDinoff 2013-05-03 16:49:02

+3

對於我們這些南亞之外,一個「十萬」根據http://en.wikipedia.org/wiki/Lakh是十萬(100,000)。 – rgettman 2013-05-03 16:50:40

+0

不,它不會被排序,因爲號碼的狀態不會發生。 base.txt文件,我們可以對它進行排序,但status.txt文件來以任意順序,也有像行大數據「5071111112,提交PLAYER1,player2,失敗,正在重試...」 – Jayesh 2013-05-03 16:53:30

回答

1

有幾種方法可以解決這個問題,它們不是Java特定的(這是人們無法理解的)。 這些是CS問題

你需要做的是找到集合'A'與集合'B'的交集 - 在Java 2就緒類中可以做到這一點(HashSet和TreeSet)。這些都由其等效的地圖類型支持。

有2種方法可以解決這個問題:

1)排序中塊ALA 二叉搜索樹文件(這意味着,對於任何排序樹子樹也被排序)。在這種情況下,您將使用您認爲可以爲較小排序處理的任何內存空間(通常,內存空間將是該文件中的條目數的某個模數)創建排序子樹。您可以將中間分類結果寫入臨時文件。

2)使用布隆過濾器可顯着減少所考慮元素的數量。創建超級集合的布隆過濾器(對於您的情況將是沒有狀態代碼的文件)。然後使用過濾器來DEFINITELY刪除永遠不會在其他集合中的元素。

如果你沒有一個清晰的超級集合,你可以應用交叉過濾,在你爲集合'A'創建一組盛放位並從'B'中刪除任何肯定不包含在'A'中的任何然後扭轉這個過程。

你最終得到的是兩個「可能」相交的小得多的集合。在這一點上,你可以使用setA.retainAll(setB)來產生公共元素。

如果你的套只是笨拙,你可以使用#2#應用1或以下

3#3)之前設置一個地圖,減少與卡桑德拉和一些virts工作。您可以設置一些EC2實例或使用內部版本。你的工作會快得多。

+0

嘿基督教,我不知道布隆過濾器,我會嘗試使用它。關於您的第三種解決方案,我們之前已經使用hadoop,但由於維護,我們希望擺脫它,因爲在這種情況下數據不會太高以至於無法使用hadoop。 – Jayesh 2013-05-04 03:18:24

0

如果文件不是非常大,您可以讀取文件並將其放入地圖中。

Map<String(Phonenumber), String(Status)> 

然後,您通過第二個文件逐行閱讀並將狀態置於地圖中。

完成後,您將遍歷Map並將其寫入合併文件。

for(Entry<String, String>e : map.entrySet()) 
    write(e.getvalue()); 

然而,如果你可以在內存中加載所有東西,這很容易,所以這取決於這些文件的真實大小。如果我們正在談論千兆字節,那麼它可能不起作用。

如果是安裝即cygwin的一個選項,這樣你就可以使用UNIX shell命令我會做這樣的(或者如果你,否則可以在一個單一的文件一起對它們進行排序):

sort -u base status > temporary 

這樣你就可以保證每個數字都是對的。 然後寫一個小的java腳本讀取每一行。記住內存中的號碼以及更多狀態消息到來時,添加它們。當下一個數字與之前不一樣時,將它寫入合併文件,這將是您的最終結果。

+0

我無法做到這一點,因爲它會用完內存。我已經嘗試過,並使用jconsole,我也可以看到。 – Jayesh 2013-05-03 16:57:11

+0

您是否嘗試使用mx選項增加內存? – Devolus 2013-05-03 16:57:43

+0

實際上通過增加MX的選擇,我可以嘗試,但我不想去的內存解決方案,我的文件將是很大的。 – Jayesh 2013-05-03 16:59:32

0

我將構建兩個輸入流並讀取base.txt的第一行和狀態。TXT 並加以比較

循環:

- 如果這些數字是相等的(請在status.txt中的子字符串,並將其與base.txt比較) 寫從base.txt和realease行兩條線

- 如果它們不相等寫一個具有較低numhber和realese它

讀取下一行(S)

這隻會工作,如果他們是由n個有序成員(否則你應該先排序)。

如果運行時間是沒有問題的,你可以很容易地實現冒泡排序,並通過線做線;)

0

假設您的文件,也可以,排序,用兩個光標像你描述的是將它們合併最佳方案。

您也可以考慮使用數據庫。

+0

嘿ykaganovich,在這種方法每次我有時間來創建新的文件,然後刪除舊的和重命名新的。是RandomAccessFile類可以幫助我在這種情況下? – Jayesh 2013-05-03 17:08:31

+0

我的直覺告訴我,創建一個新文件更具有高性能。 – ykaganovich 2013-05-03 20:32:27

0

我只是想和實施一個解決方案與您的帖子的幫助,並獲得所需的結果。 只是想確認是否是好的解決方案。

現在第一步,我整理我的base.txt文件

在第二個步驟,我分裂我的base.txt文件,其中包含大約10,00,000號到許多文件,包括1,00,000號在每個文件中(我在考慮拆分文件,而不是通過使用HashMap或其他內容獲取完整的10,00,000個數字),我可能會進入內存不足錯誤。

現在基礎文件被拆分成塊。我維護1個索引文件,用於跟蹤分割文件中的數字。

limit     file-name 
1-1,00,000   split0.txt 
1,00,001-2,00,000  split1.txt 

現在,我開始閱讀status.txt文件,並選擇從它一個號,我有合併,索引文件的幫助,我會確切地知道我要挑對更新的文件。現在

,因爲有塊文件包含大約1,00,000號(說split4.txt),我是把它HashMap和更新正確的記錄,並再次寫的HashMap到該文件。

我用這個解決方案得到期望的結果,只是想確認,它是正確的做法還是我缺少什麼。

謝謝