【问题标题】:Out of memory using Scanner to read large file into memory使用扫描仪将大文件读入内存时内存不足
【发布时间】:2013-09-12 09:54:14
【问题描述】:

当我将大文件传递到扫描仪时,以下代码块会引发 java.lang.OutOfMemoryError 异常。解决此问题的最佳方法是什么?是数组列表的问题还是扫描仪的问题?

ArrayList rawData = new ArrayList();
Scanner scan = new Scanner(file);

while (scan.hasNext()) {
    String next = scan.next();
        rawData.add(next);
}

【问题讨论】:

  • 这里的问题不是Scanner, 它正在将大文件读入内存。你不能一次处理一行吗?

标签: java arraylist java.util.scanner heap-memory


【解决方案1】:

主要问题是存储在数组列表中。此外,尝试使用 bufferReader 并在 while 语句中进行处理,而不是尝试将其添加到数组列表中。这是一个简单的例子。

        File file = new File("C:\\custom_programs\\reminder_list.txt");
        BufferedReader br = new BufferedReader(new FileReader(file));
        String line;
        while ((line = br.readLine()) != null) {
            // do something with line.
            System.out.println(line);
        }
        br.close();

【讨论】:

    【解决方案2】:

    Scanner 的默认分隔符是空格。

    public Scanner(ReadableByteChannel source) { // Your File is converted to a ReadableByteChannel from another constructor 
        this(makeReadable(Objects.requireNonNull(source, "source")),
             WHITESPACE_PATTERN);
    }
    

    所以如果你的文件包含很多空白字符,你会循环很多次

    while (scan.hasNext()) {
        String next = scan.next();
        rawData.add(next);
    }
    

    在您的 ArrayList 中放入许多对象,但不收集任何垃圾(即不释放内存)。

    每次调用next() 都会返回下一个标记,直到找到空格为止。更改分隔符、增加内存大小或更改设计。

    你的文件格式是什么?

    【讨论】:

      【解决方案3】:

      不要将文件中的所有行都加载到ArrayList 中,而是在读取每条记录后立即对它执行您想要的操作。如果 heapsize 不够大,将整个文件加载到内存中会导致 OOM 问题。

      Scanner scan = new Scanner(file);
      while (scan.hasNext()) {
          String next = scan.next();
          //do what you want to do on next
      }
      

      【讨论】:

        【解决方案4】:

        增加java堆大小,例如

        java -Xmx6g myprogram
        

        将堆大小设置为 6 GB。当然总会有限制的......

        【讨论】:

        • 我更喜欢一种优化代码的方法,而不是要求每次运行程序时都更改堆大小。有什么建议吗?
        • @trentjones21 是的,但我需要知道你想对数据做什么。正如您问题的另一个答案中所建议的那样,您可能应该将每一行或您想要处理的任何块作为读取处理,而不是在内存中缓冲整个内容。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-04
        • 2023-04-09
        • 2021-08-16
        • 1970-01-01
        • 2013-12-04
        相关资源
        最近更新 更多