在Java中读取3GB的非常大的csv文件的内存有效方法是什么?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Java中读取3GB的非常大的csv文件的内存有效方法是什么?相关的知识,希望对你有一定的参考价值。

我写了两种方法来读取文件

 public static void parseCsvFile(String path) throws IOException {
    FileInputStream inputStream = null;
    Scanner sc = null;
    try {
        inputStream = new FileInputStream(path);
        sc = new Scanner(inputStream, "UTF-8");
        while (sc.hasNextLine()) {
            String line = sc.nextLine();
            //logger.info(line);
        }
        // note that Scanner suppresses exceptions
        if (sc.ioException() != null) {
            throw sc.ioException();
        }
    } finally {
        if (inputStream != null) {
            inputStream.close();
        }
        if (sc != null) {
            sc.close();
        }
    }
  }

    public static void parseCsvUsingJavaStream(String path) {
    try (Stream<String> stream = Files.lines(Paths.get(path))) {
         stream.forEach(System.out :: println);
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }
  }

从第一种方法我理解的是,该方法不会立即将文件中的所有行加载到内存中,这是内存高效的。我希望使用lambda表达式实现相同的功能。我的问题是我的第二种方法是否将所有行加载到内存中?如果是,那么如何才能使我的第二种方法内存有效?

答案

您的问题的答案在Files.lines javadoc

从文件中读取所有行作为流。与readAllLines不同,此方法不会将所有行读入List,而是在使用流时延迟填充。

您的第二个代码示例应与您的第一个代码示例大致相同,具有内存效率。

另一答案

除非您并行化流,否则使用流api应该导致与其他方法大致相同的内存使用量。

来自Javadoc

从文件中读取所有行作为流。与readAllLines不同,此方法不会将所有行读入List,而是在使用流时延迟填充。

使用指定的字符集将文件中的字节解码为字符,并支持readAllLines指定的相同行终止符。

在此方法返回之后,从读取文件或读取格式错误或不可映射的字节序列时发生的任何后续I / O异常都包含在将从Stream方法抛出的UncheckedIOException中,该方法导致读取发生。如果在关闭文件时抛出IOException,它也会被包装为UncheckedIOException。

返回的流封装了一个Reader。如果需要及时处理文件系统资源,则应使用try-with-resources构造来确保在流操作完成后调用流的close方法。

以上是关于在Java中读取3GB的非常大的csv文件的内存有效方法是什么?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python 或 R 将非常大的 sql 文件导出到 csv

如何使用 Windows Batch 读取和编辑 (>3GB) csv 文件?

为啥使用 php 从一个非常大的 csv 文件中只读取 1000 条记录?

在 R 中读取大型 csv 文件

大型 CSV 文件 (numpy) 上的 Python 内存不足

在python中逐行读取一个大的压缩文本文件