[英]Quickest way to read text-file line by line in Java
對於日志處理,我的應用程序需要逐行讀取文本文件。 首先我使用了 BufferedReader 的 function readLine() 但我在網上看到 BufferedReader 在讀取文件時速度很慢。
之后我嘗試將 FileInputStream 與 FileChannel 和 MappedByteBuffer 一起使用,但在這種情況下,沒有類似於 readLine() 的 function 所以我在我的文本中搜索換行符並處理它:
try {
FileInputStream f = new FileInputStream(file);
FileChannel ch = f.getChannel( );
MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, 0L, ch.size());
byte[] bytes = new byte[1024];
int i = 0;
while (mb.hasRemaining()) {
byte get = mb.get();
if(get == '\n') {
if(ra.run(new String(bytes)))
cnt++;
for(int j = 0; j<=i; j++)
bytes[j] = 0;
i = 0;
}
else
bytes[i++] = get;
}
} catch(Exception ex) {
ex.printStackTrace();
}
我知道這可能不是實現它的好方法,但是當我以字節為單位讀取文本文件時,它比使用 BufferedReader 快 3 倍,但調用new String(bytes)
會創建一個新 String 並使程序變得更慢使用 BufferedReader。
所以我想問一下逐行讀取文本文件的最快方法是什么? 有人說 BufferedReader 是解決這個問題的唯一方法。
PS: ra
是來自 dk.brics.Automaton 庫的 RunAutomaton 的一個實例。
我非常懷疑BufferedReader
會導致大量開銷。 添加您自己的代碼可能至少效率低下,而且很可能也是錯誤的。
例如,在您提供的代碼中,您正在調用new String(bytes)
,它總是會使用平台默認編碼從 1024 個字節創建一個字符串……這不是一個好主意。 當然,之后你清除了數組,但是你的字符串仍然會包含一堆 '\0' 字符——這意味着除了其他任何東西之外,還會浪費很多空間。 您至少應該限制正在從中創建字符串的字節數組部分(這也意味着您之后不需要清除數組)。
您是否真的嘗試過使用BufferedReader
並發現它太慢了? 您通常應該首先編寫最簡單的代碼來滿足您的目標,然后檢查它是否足夠快......特別是如果您不這樣做的唯一原因是您“在互聯網上閱讀”的未指定資源。 你想讓我找到數百個提出不正確性能建議的人的例子嗎? :)
作為替代方案,您可能想查看Guava的Files.readLines()
重載,它采用LineProcessor
。
使用普通的 BufferedReader 我得到了 100+ MB/s 。 您可以從磁盤讀取數據的速度很可能是您的瓶頸,因此您如何進行讀取不會有太大的不同。
BufferedReader 不是唯一的解決方案,但它對於 99% 的用例來說已經足夠快了,那么為什么要讓事情變得比需要的更復雜呢?
框架是替代品嗎?
我不知道性能,但是
http://commons.apache.org/io/api-release/index.html參見 IOUtils ZA24F2ED4F8EBCA6CBB14F2ED4F8EBCA2
為這種情況定義了非常易於使用的輔助類。
我有一個非常簡單的循環,它使用 BufferedReader 從 sdcard 上的文件中讀取大約 2000 行(50k 字節),並在 Galaxy 選項卡 2 的調試模式下在大約 100 毫秒內讀取它們。還不錯。 然后我把一個掃描儀放在循環中,時間過了屋頂(幾十秒),加上很多 GC_CONCURANT 消息
Scanner scanner = new Scanner(line);
int eventType = scanner.nextInt(16);
所以至少在我的情況下,問題在於掃描儀,我想我需要以另一種方式掃描整數,但我不知道為什么它會這么慢
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.