Java 大文件读取

1. 简介

这篇文章主要是讲解展示,在Java中如何高效的读取大文件中的数据。

2. 内存里读取

一般情况下,我们都是在内存中读取文件——Guava 和 Apache Commons IO 提供了快速的方法:

Files.readLines(new File(path), Charsets.UTF_8);
    FileUtils.readLines(new File(path));<br />
这样做的方法有个问题就是,文件会被保存在内存中,如果文件太大的话,会造成OutOfMemoryError 下面举个例子,读取1Gb的文件:
@Test
    public void givenUsingGuava_whenIteratingAFile_thenWorks() throws IOException {
        String path = ...
        Files.readLines(new File(path), Charsets.UTF_8);
    }
刚开始内存使用:
[main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 128 Mb
    [main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 116 Mb
读取所有文件后,我们再来看看内存使用
[main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 2666 Mb
    [main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 490 Mb
我们可以看到。大约2.1Gb的内存被消耗。原因很简单,这个方法将文件完全加载到了内存当中。 通过以上的验证,我们可以清楚的知道。将所有的文件都保存在内存中是非常消耗内存的。 还有就是,我们通常也不需要把文件都放在内存中来读。我们需要的是对文件的循环读取,需要的功能是读取——处理——丢弃。我们要做的就是,依次读取依次遍历所有的文件。

3. 通过流来读取文件

现在我们来看一下解决方法,我们用到java.util.Scanner 来获取文件内容,并且依次读取数据内容:

FileInputStream inputStream = null;
    Scanner sc = null;
    try {
        inputStream = new FileInputStream(path);
        sc = new Scanner(inputStream, "UTF-8");
        while (sc.hasNextLine()) {
            String line = sc.nextLine();
            // System.out.println(line);
        }
        // note that Scanner suppresses exceptions
        if (sc.ioException() != null) {
            throw sc.ioException();
        }
    } finally {
        if (inputStream != null) {
            inputStream.close();
        }
        if (sc != null) {
            sc.close();
        }
    }
这个方法遍历了文件所有内容,可以处理每一行的记录。没有将内容一直存在内存中:
[main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 763 Mb
    [main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 339 Mb</p>

4. 结束语

这篇文章就讲解了读取一个大文件的一个不错的方法。可以减少一些不必要的内存使用

你可能感兴趣的:(java,大文件)