簡體   English   中英

在 Java 中逐行讀取文本文件的最快方法

[英]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並發現它太慢了? 您通常應該首先編寫最簡單的代碼來滿足您的目標,然后檢查它是否足夠快......特別是如果您不這樣做的唯一原因是您“在互聯網上閱讀”的未指定資源。 你想讓我找到數百個提出不正確性能建議的人的例子嗎? :)

作為替代方案,您可能想查看GuavaFiles.readLines()重載,它采用LineProcessor

使用普通的 BufferedReader 我得到了 100+ MB/s 您可以從磁盤讀取數據的速度很可能是您的瓶頸,因此您如何進行讀取不會有太大的不同。

BufferedReader 不是唯一的解決方案,但它對於 99% 的用例來說已經足夠快了,那么為什么要讓事情變得比需要的更復雜呢?

框架是替代品嗎?

我不知道性能,但是

http://commons.apache.org/io/

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);

所以至少在我的情況下,問題在於掃描儀,我想我需要以另一種方式掃描整數,但我不知道為什么它會這么慢

根據這篇SO 帖子,您可能還想試一試掃描儀class。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM