2012-01-11 37 views
7

我必須閱讀一個大的文本文件,比如說25GB,並且需要在15-20分鐘內處理這個文件。該文件將具有多個頁眉和頁腳部分。閱讀和處理25GB大文本文件

我試圖CSPLIT分裂基於頭這個文件,但它正在約24至25分鐘,將其分割爲多個文件,基於報頭,這是不能接受的。

我試着用BufferReaderBufferWiter以及FileReaderFileWriter連續讀取和寫入。它需要超過27分鐘。再次,這是不可接受的。

我試着像得到每頭開始指數的另一種方法,然後運行多個線程使用RandomAccessFile來讀取特定位置的文件。但沒有這個運氣。

我該如何達到我的要求?

的可能重複:

Read large files in Java

回答

7

嘗試使用大緩衝區讀取大小(例如,20MB,而不是2MB)來處理數據更快。由於速度和字符轉換速度慢,請勿使用BufferedReader。

這個問題已經被問過:Read large files in Java

0

嘗試使用java.nio以更好地利用操作系統的功能。避免複製數據(例如,轉換爲字符串),但嘗試使用偏移量。我相信java.nio類甚至會有方法將數據從一個緩衝區傳輸到另一個緩衝區,而根本不會將數據拉到Java層(至少在linux上),但是這基本上會轉化爲操作系統調用。

對於許多現代的Web服務器該技術已關鍵,他們可以成爲靜態數據的表現:基本上他們委託儘可能操作系統,以避免它複製到主存儲器。

讓我強調這一點:剛剛經歷了25 GB字節的緩衝區尋求比它轉換成Java字符串(這可能需要字符集編碼/解碼 - 和複製)快很多。任何可以節省你的副本和內存管理的東西都會有所幫助

+1

NIO有其自己的醜陋限制:您最多可以將2GB映射爲緩衝區,因爲Buffer API對所有偏移使用int。對於大文件來說,這使得nio很麻煩。 – Durandal 2012-01-11 11:27:25

5

您需要確保IO是沒有你的處理速度不夠快,因爲我懷疑的處理,而不是IO正在放緩你失望。您應該能夠從硬盤驅動器獲得80 MB/s,從SSD驅動器獲得高達400 MB/s的速度。這意味着你可以在一秒鐘內閱讀完整內容。

請嘗試以下操作,這不是最快的操作,而是最簡單的操作。

long start = System.nanoTime(); 
byte[] bytes = new byte[32*1024]; 
FileInputStream fis = new FileInputStream(fileName); 
int len; 
while((len = fis.read(bytes)) > 0); 
long time = System.nanoTime() - start; 
System.out.printf("Took %.3f seconds%n", time/1e9); 

除非您發現您至少有50 MB/s,否則您有硬件問題。

0

如果平臺是正確的,你可能要掏出,並呼籲貓和sed的組合。如果不是的話,你可能還想通過命令行來釋放並使用perl。對於絕對必須由Java進行實際處理的情況,其他人已經提供了足夠的答案。

儘管如此,炮擊並非沒有問題。但是perl或sed可能是在您的時間範圍內爬行並更改25GB文本的唯一可用工具。