在java中处理大文件

时间:2016-06-25 15:39:56

标签: java java-stream

如何解析1.2GB这样的大文件,其中文件中的总行数为36259190。如何将每一行解析为一个对象并将其保存在列表中。

我每次都会得到OutOfMemmoryError

List<Point> points = new ArrayList<>();

public void m2() throws IOException {
    try (BufferedReader reader = Files.newBufferedReader(Paths.get(DATAFILE))) {
        reader.lines().map(s -> s.split(","))
        .skip(0)
        .forEach(p -> points.add(newPoint(p[0], p[1], p[2])));
    }
}


class Point {
    String X;
    String Y;
    String Z;
}

3 个答案:

答案 0 :(得分:1)

您需要使用命令行参数-Xms(最小内存)-Xmx(最大内存)。

示例:

-Xmx4G (4GB)
-Xmx200M (200MB)
java -jar program.jar -Xmx8G

答案 1 :(得分:1)

Shiro的回答是正确的,为Java分配更多内存。

数据库

如果你买不起内存,那就用一个数据库吧。例如,Postgres或H2。

数据库的目的之一是将数据保存到存储,同时有效地处理查询内存并根据需要加载数据。

在读取数据文件的每一行时,请立即存储在数据库中。稍后查询所需记录。仅在内存中为来自该查询结果集的所需行实例化对象。

答案 2 :(得分:1)

关注您的数据类型。我很确定你的观点不包含三个文本片段。因此,请根据实际类型定义Point的字段,例如使用intdouble。这些原始数据类型比String表示消耗的内存要少得多。

class Point {
    double x, y, z;
    Point(double x, double y, double z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }
    Point(String x, String y, String z) {
        this.x = Double.parseDouble(x);
        this.y = Double.parseDouble(y);
        this.z = Double.parseDouble(z);
    }
}

然后将您的数据文件收集为

public List<Point> m2() throws IOException {
    try(BufferedReader reader = Files.newBufferedReader(Paths.get(DATAFILE))) {
        return reader.lines().map(s -> s.split(","))
            .map(a -> new Point(a[0], a[1], a[2]))
            .collect(Collectors.toList());
    }
}

然后,正如其他人所说,关心为JVM分配的内存。使用上面的point类,你可以使用~1½GiB的堆来处理36个Mio实例而没有问题......