簡體   English   中英

java中的RandomAccessFile是否讀取內存中的整個文件?

[英]Does RandomAccessFile in java read entire file in memory?

我需要從大文件中讀取最后n行(比如2GB)。 該文件是UTF-8編碼的。

想知道最有效的方法。 在java中讀取RandomAccessFile,但是seek()方法讀取內存中的整個文件。 它使用本機實現,因此我無法引用源代碼。

  1. RandomAccessFile.seek只設置文件指針的當前位置,沒有字節被讀入內存。

  2. 由於您的文件是UTF-8編碼的,因此它是一個文本文件。 對於讀取文本文件,我們通常使用BufferedReader,Java 7甚至添加了一個方便的方法File.newBufferedReader來創建BufferedReader的實例來從文件中讀取文本。 盡管讀取最后n行可能效率低,但易於實現。

  3. 為了提高效率,我們需要RandomAccessFile並從結尾開始向后讀取文件。 這是一個基本的例子

public static void main(String[] args) throws Exception {
    int n = 3;
    List<String> lines = new ArrayList<>();
    try (RandomAccessFile f = new RandomAccessFile("test", "r")) {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        for (long length = f.length(), p = length - 1; p > 0 && lines.size() < n; p--) {
            f.seek(p);
            int b = f.read();
            if (b == 10) {
                if (p < length - 1) {
                    lines.add(0, getLine(bout));
                    bout.reset();
                }
            } else if (b != 13) {
                bout.write(b);
            }
        }
    }
    System.out.println(lines);
}

static String getLine(ByteArrayOutputStream bout) {
    byte[] a = bout.toByteArray();
    // reverse bytes
    for (int i = 0, j = a.length - 1; j > i; i++, j--) {
        byte tmp = a[j];
        a[j] = a[i];
        a[i] = tmp;
    }
    return new String(a);
}

它讀取從tail到ByteArrayOutputStream的字節后的文件字節,當達到LF時,它會反轉字節並創建一行。

有兩件事需要改進:

  1. 緩沖

  2. EOL識別

如果您需要隨機訪問,則需要RandomAccessFile。 如果您知道自己在做什么,可以將從中獲得的字節轉換為UTF-8。

如果使用BuffredReader,則可以使用skip(n)字符數,這意味着它必須讀取整個文件。


一種組合方式; 是使用帶有skip()的FileInputStream,通過讀回N個換行符找到要讀取的位置,然后將流包裝在BufferedReader中以讀取具有UTF-8編碼的行。

暫無
暫無

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

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