是否RandomAccessFile的在java中读取内存整个文件?(Does RandomAcce

2019-07-23 05:00发布

我需要阅读从一个大文件的最后n行(说2GB)。 该文件是UTF-8编码。

想知道这样做的最有效的方式。 阅读关于RandomAccessFile的在Java中,但它的seek()方法,读取内存中的整个文件。 它采用原生实现,所以我没能参考的源代码。

Answer 1:

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

它读取的字节开始从尾部到ByteArrayOutputStream后的文件字节,当达到LF它反转字节,并创建一个行。

有两件事情需要改进:

  1. 缓冲

  2. EOL识别



Answer 2:

如果你需要随机访问,你需要的RandomAccessFile。 你可以把你从这个进入UTF-8字节,如果你知道自己在做什么。

如果你使用BuffredReader,您可以使用跳过(n)的字符数,这意味着它具有读取整个文件。


一种方法相结合来做到这一点; 是使用的FileInputStream与跳跃(),查找想从读出由读回Ñ换行符,然后包裹在的BufferedReader流中读取使用UTF-8编码的行。



文章来源: Does RandomAccessFile in java read entire file in memory?