解决java读取大文件内存溢出问题、如何在不重复读取与不耗尽内存的情况下处理大文件
来源:互联网 发布:电脑解压软件下载 编辑:程序博客网 时间:2024/05/21 15:07
解决java读取大文件内存溢出问题、如何在不重复读取与不耗尽内存的情况下处理大文件
分类:
目录(?)[+]
1、传统的在内存中读取
读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速读取文件行的方法:
1
2
3
Files.readLines(
new
File(path), Charsets.UTF_8);
FileUtils.readLines(
new
File(path));
这种方法带来的问题是文件的所有行都被存放在内存中,当文件足够大时很快就会导致程序抛出OutOfMemoryError 异常。
例如:读取一个大约1G的文件:
1
2
3
4
5
@Test
public
void
givenUsingGuava_whenIteratingAFile_thenWorks()
throws
IOException {
String path = ...
Files.readLines(
new
File(path), Charsets.UTF_8);
}
这种方式开始时只占用很少的内存:(大约消耗了0Mb内存)
1
2
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory:
128
Mb
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory:
116
Mb
然而,当文件全部读到内存中后,我们最后可以看到(大约消耗了2GB内存):
1
2
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory:
2666
Mb
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory:
490
Mb
这意味这一过程大约耗费了2.1GB的内存——原因很简单:现在文件的所有行都被存储在内存中。
把文件所有的内容都放在内存中很快会耗尽可用内存——不论实际可用内存有多大,这点是显而易见的。
此外,我们通常不需要把文件的所有行一次性地放入内存中——相反,我们只需要遍历文件的每一行,然后做相应的处理,处理完之后把它扔掉。所以,这正是我们将要做的——通过行迭代,而不是把所有行都放在内存中。
2、文件流
现在让我们看下这种解决方案——我们将使用Java.util.Scanner类扫描文件的内容,一行一行连续地读取:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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();
}
}
这种方案将会遍历文件中的所有行——允许对每一行进行处理,而不保持对它的引用。总之没有把它们存放在内存中:(大约消耗了150MB内存)
1
2
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory:
763
Mb
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory:
605
Mb
3、Apache Commons IO流
同样也可以使用Commons IO库实现,利用该库提供的自定义LineIterator:
1
2
3
4
5
6
7
8
9
LineIterator it = FileUtils.lineIterator(theFile,
"UTF-8"
);
try
{
while
(it.hasNext()) {
String line = it.nextLine();
// do something with line
}
}
finally
{
LineIterator.closeQuietly(it);
}
由于整个文件不是全部存放在内存中,这也就导致相当保守的内存消耗:(大约消耗了150MB内存)
1
2
[main] INFO o.b.java.CoreJavaIoIntegrationTest - Total Memory:
752
Mb
[main] INFO o.b.java.CoreJavaIoIntegrationTest - Free Memory:
564
Mb
4、结论
这篇短文介绍了如何在不重复读取与不耗尽内存的情况下处理大文件——这为大文件的处理提供了一个有用的解决办法。
阅读全文
0 0
- 解决java读取大文件内存溢出问题、如何在不重复读取与不耗尽内存的情况下处理大文件
- 解决java读取大文件内存溢出问题、如何在不重复读取与不耗尽内存的情况下处理大文件
- 解决java读取大文件内存溢出问题、如何在不重复读取与不耗尽内存的情况下处理大文件
- 解决java读取大文件内存溢出问题、如何在不重复读取与不耗尽内存的情况下处理大文件
- php 如何在有限的内存中读取大文件
- 用内存映射文件解决大文件读取问题
- 用C语言读取大文件的问题 内存映射
- 用C语言读取大文件的问题 内存映射
- 用C语言读取大文件的问题 内存映射
- 用C语言读取大文件的问题 内存映射
- Excel大文件时读取内存溢出的解决方案,测试50M的Excel通过。
- Java读取大文件的处理
- java如何读取大文件
- java 如何读取大文件
- java 读 大文件excel 内存溢出 解决
- 使用内存映射文件加快读取大文件的速度 .
- 用内存映射文件的方式读取大文件
- c++ windows下读取大文件(内存映射)
- 计算机图形学之光线跟踪算法的研究与实现2017年我的优秀毕业论文
- Linux obj 定义描述
- HTTP权威指南 文字版 带目录
- IT修真院是个什么样的机构?
- 对称排序
- 解决java读取大文件内存溢出问题、如何在不重复读取与不耗尽内存的情况下处理大文件
- 只有想不到,没有做不到
- ES5,ES6互相转换
- 分布式搜索elasticsearch配置文件详解
- Golang 获得文件名最快的代码实现方式比较
- php7新特性
- spring中packagesToScan的解释
- GitHub 的 Fork 是什么意思?
- mysql5.5.44在win10的cmd下插入中文提示Incorrect string value