2010-08-20 58 views
1

我有一個大小爲2GB的文件,其中有學生記錄。我需要根據每條記錄中的某些屬性找到學生,並創建一個包含結果的新文件。過濾學生的順序應與原始文件中的順序相同。使用Java IO API和線程執行此操作的最快方法是什麼,而沒有內存問題? JVM的maxheap大小設置爲512MB。java中的文件處理

+2

考慮將信息存儲在數據庫而不是2GB文件中。爲學生做。 – polygenelubricants 2010-08-20 01:14:39

+0

數據庫不適合我。我會用純文本文件獲取數據,我必須處理它。 – 2010-08-20 01:19:17

+0

無法將X磅的任何東西放入X/N包中,其中N> 1。您將永遠不會將該文件的全部內容一次性壓縮到內存中。 – duffymo 2010-08-20 01:24:49

回答

6

什麼樣的文件?基於文本的,如CSV?

最簡單的方法是做類似grep的事情:逐行讀取文件,解析行,檢查過濾條件,如果匹配,輸出結果行,然後轉到下一行,直到文件已經完成了。這非常有效,因爲您只有當前行(或緩衝區稍大)加載的同時。你的過程需要通讀整個文件一次。

我不認爲多線程會有很大的幫助。這會讓事情變得更加複雜,並且由於無論如何這個過程似乎都是I/O約束,試圖用多個線程讀取同一個文件可能不會提高吞吐量。

如果你發現你需要經常這樣做,每次瀏覽文件太慢,你需要建立某種索引。最簡單的方法是先將文件導入數據庫(可以是SQLite或HSQL等嵌入式數據庫)。

+0

哦,男孩,我打字完全一樣的答案。事實上,所有這些都歸結爲只是一行一行地完成這項工作,而不是將整個事情存儲在Java的內存中。 – BalusC 2010-08-20 01:34:17

5

我不會過度複雜,直到你發現無聊簡單的方式不適合你的需要。從本質上講,你只需要:

  • 打開的輸入流爲2GB的文件,記住緩衝液(如用的BufferedInputStream包裝)
  • 打開的輸出流過濾的文件,你要創建
  • 讀第一條記錄從輸入流中,查看任何屬性來決定是否「需要」它;如果這樣做,將其寫入到輸出文件
  • 重複的剩餘記錄

我與極爲有限的硬件測試系統之一,圍繞一個FileInputStream的BufferedInputStream開箱即在25秒內,即閱讀約500 MB大概在2分鐘內處理你的2GB文件,並且默認的緩衝區大小基本上和它一樣好(參見我所做的BufferedInputStream timings瞭解更多細節)。我想用最先進的硬件設備很可能時間會減半。

無論您需要花費很多精力來減少2/3分鐘,或者只是在等待它運行的時間裏等待一小段時間,您需要根據您的要求做出決定。我認爲數據庫選項不會給你多少錢,除非你需要在同一組數據上做很多不同的處理運行(還有其他解決方案不會自動錶示數據庫)。

+0

+1,尤指因爲「在你等待的時候過一小會兒」 – 2010-08-20 04:16:42

0

我認爲你應該使用memory mapped files.This將幫助你映射較大的文件到一個 較小的內存。這將像虛擬內存一樣行事,就性能而言,映射文件比流寫/讀。