rev*_*evy 5 java file bufferedreader
我有12000行的csv文件。每行都有几个用双引号引起来并用逗号分隔的字段。此字段之一是xml文档,因此该行可能很长。文件大小为174 Mb。
这是文件的示例:
"100000","field1","field30","<root><data>Hello I have a
line break</data></root>","field31"
"100001","field1","field30","<root><data>Hello I have multiple
line
break</data></root>","field31"
Run Code Online (Sandbox Code Playgroud)
此文件的问题在xml字段内,该字段可能具有一个或多个换行符,因此可能会中断解析。此处的目标是读取整个文件并应用正则表达式,它将用空字符串替换双引号内的所有换行符。
以下代码给了我OutOfMemoryError:
String path = "path/to/file.csv";
try {
byte[] content = Files.readAllBytes(Paths.get(path));
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
Run Code Online (Sandbox Code Playgroud)
我还尝试使用BufferedReader和StringBuilder读取文件,在第5000行附近出现OutOfMemoryError:
String path = "path/to/file.csv";
try {
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new FileReader(path));
String line;
int count = 0;
while ((line = br.readLine()) != null) {
sb.append(line);
System.out.println("Read " + count++);
}
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用不同的Java堆值(如-Xmx1024m,-Xmx4096m,-Xmx8092m)运行以上两个程序。在所有情况下,我都遇到了OutOfMemoryError。考虑到文件大小为174Mb,为什么会发生这种情况?
您需要使用双缓冲区来解析您的特殊数据结构,并逐行处理它们。阅读整个文档并不是最好的主意。
创建一个自己的BufferedReader文件来读取BufferedReaderCSV 文件内部的行。读取一行后,尝试确定是否需要读取更多行来完成 CSV 中的一行(例如,如果您知道 XML 以 开头<root>和结尾</root>,请检查这些字符串是否存在,然后读取并追加,直到到达结束标记 - 这将是 CSV 行的最后一行)。
第二层将是您的 CSV 处理,基于您从第一步获得的 CSV 行。解析它,保存它,处理它,然后抛出它。那么它就不会消耗更多的内存空间,Java垃圾收集器会释放它。
这是处理大文件的唯一方法。它也被称为“流模型”,因为你只传递小块数据,所以实际的内存消耗很低。