Java读取大文件的高效率实现
1、概述
本教程将演示如何用Java高效地读取大文件。这篇文章是Baeldung (http://www.baeldung.com/) 上“Java——回归基础”系列教程的一部分。
2、在内存中读取
读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速读取文件行的方法:
Files.readLines(new File(path), Charsets.UTF_8); FileUtils.readLines(new File(path));
这种方法带来的问题是文件的所有行都被存放在内存中,当文件足够大时很快就会导致程序抛出OutOfMemoryError 异常。
例如:读取一个大约1G的文件:
@Test
public void givenUsingGuava_whenIteratingAFile_thenWorks() throws IOException {
String path = ...
Files.readLines(new File(path), Charsets.UTF_8);
}
这种方式开始时只占用很少的内存:(大约消耗了0Mb内存)
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 128 Mb
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 116 Mb
然而,当文件全部读到内存中后,我们最后可以看到(大约消耗了2GB内存):
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 2666 Mb
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 490 Mb
这意味这一过程大约耗费了2.1GB的内存——原因很简单:现在文件的所有行都被存储在内存中。
把文件所有的内容都放在内存中很快会耗尽可用内存——不论实际可用内存有多大,这点是显而易见的。
此外,我们通常不需要把文件的所有行一次性地放入内存中——相反,我们只需要遍历文件的每一行,然后做相应的处理,处理完之后把它扔掉。所以,这正是我们将要做的——通过行迭代,而不是把所有行都放在内存中。
3、文件流
现在让我们看下这种解决方案——我们将使用java.util.Scanner类扫描文件的内容,一行一行连续地读取:
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内存)
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 763 Mb
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 605 Mb
4、Apache Commons IO流
同样也可以使用Commons IO库实现,利用该库提供的自定义LineIterator:
LineIterator it = FileUtils.lineIterator(theFile, "UTF-8");
try {
while (it.hasNext()) {
String line = it.nextLine();
// do something with line
}
} finally {
LineIterator.closeQuietly(it);
}
由于整个文件不是全部存放在内存中,这也就导致相当保守的内存消耗:(大约消耗了150MB内存)
[main] INFO o.b.java.CoreJavaIoIntegrationTest - Total Memory: 752 Mb
[main] INFO o.b.java.CoreJavaIoIntegrationTest - Free Memory: 564 Mb
5、结论
这篇短文介绍了如何在不重复读取与不耗尽内存的情况下处理大文件——这为大文件的处理提供了一个有用的解决办法。
所有这些例子的实现和代码片段都可以在我的github项目上获取到——这是一个基于Eclipse的项目,所以它应该很容易被导入和运行。
Java读取大文件的高效率实现的更多相关文章
- java读取 500M 以上文件,java读取大文件
java 读取txt,java读取大文件 设置缓存大小BUFFER_SIZE ,Config.tempdatafile是文件地址 来源博客http://yijianfengvip.blog.163.c ...
- java 读取txt,java读取大文件
java 读取txt,java读取大文件 package com.bbcmart.util; import java.io.File;import java.io.RandomAccessFile;i ...
- java读取大文件
1 多线程 2 java内存映射读取大文件
- Java 读取大文件方法
需求:实际开发中读取文本文件的需求还是很多,如读取两个系统之间FTP发送文件,读取后保存到数据库中或日志文件的数据库中保存等. 为了测试首先利用数据库SQL生成大数据文件. 规则是 编号|姓名|手机号 ...
- java读取大文件 超大文件的几种方法
java 读取一个巨大的文本文件既能保证内存不溢出又能保证性能 import java.io.BufferedReader; import java.io.File; import jav ...
- java读取大文件内容到Elasticsearch分析(手把手教你java处理超大csv文件)
现在需要快算分析一个2g的csv文件: 基于掌握的知识,使用java按行读取文件,批量导入数据到es, 然后利用es强大的聚合能力分析数据,2个小时搞定! package com.example.de ...
- 解决java读取大文件内存溢出问题
1. 传统方式:在内存中读取文件内容 读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速读取文件行的方法: Files.readLines(new ...
- Java多线程读取大文件
前言 今天是五一假期第一天,按理应该是快乐玩耍的日子,但是作为一个北漂到京师的开发人员,实在难想出去那玩耍.好玩的地方比较远,近处又感觉没意思.于是乎,闲着写篇文章,总结下昨天写的程序吧. 昨天下午朋 ...
- java 分次读取大文件的三种方法
1. java 读取大文件的困难 java 读取文件的一般操作是将文件数据全部读取到内存中,然后再对数据进行操作.例如 Path path = Paths.get("file path&qu ...
随机推荐
- 使用java中的注解@see
缘起 在写java时,有时需要写注释,而为了更好的描述,需要引用和参考其他代码.为了让阅读者更好的体验,javadoc中支持链接跳转,这就需要用到注解@see. @see用法 注解@see可以在注释中 ...
- opencv 矩阵类数据的运算
参考:http://blog.sina.com.cn/s/blog_7908e1290101i97z.htmlhttp://blog.sina.com.cn/s/blog_afe2af380101bq ...
- HDU——1573 X问题
又来一发水题. 解同余方程而已,用类似于剩余定理的方法就O了. 直接上代码:(注意要判断是否有解这种情况) #include <iostream> #include <cstdio& ...
- 运维朋友们,别再问需不需要学 Python 了!
运维人员需不需要学开发?需不需要学 Python?PythonN 和 Shell 有什么区别?天天问这种好水的问题,我实在受不了,决定帮大家扫扫盲. 现阶段,掌握一门开发语言已经成为高级运维工程师的必 ...
- 【HLSDK系列】服务端实体 edict_t 和 控制类
我们来了解一下引擎是怎么管理实体的吧!我们这里就说说服务端的实体(edict_t) 服务端用 edict_t 这个结构体来保存一个实体,可以说一个 edict_t 就是一个 服务端实体,下文简称实体. ...
- 【题解】JSOI2011分特产
没sa可suo的,sui题一道…… #include <bits/stdc++.h> using namespace std; #define maxn 3000 #define mod ...
- 【MVVM Dev】PART_Editor的使用
一.前言 在日常的界面开发中,我们大多使用MVVM模式进行开发.通常情况下,一个PropertyGridControl或者DataGrid的ItemsSource设置好, 然后每一列绑定好 ...
- (转)搭建本地 8.8 W 乌云漏洞库
下载地址: 开源地址: https://github.com/m0l1ce/wooyunallbugs 百度网盘: 链接: http://pan.baidu.com/s/1nvkFKox 密码: 94 ...
- mysql互为主从复制配置笔记--未读,稍后学习
MySQL-master1:192.168.72.128 MySQL-master2:192.168.72.129 OS版本:CentOS 5.4MySQL版本:5.5.9(主从复制的master和s ...
- Linux基础------文件打包解包---tar命令,文件压缩解压---命令gzip,vim编辑器创建和编辑正文件,磁盘分区/格式化,软/硬链接
作业一:1) 将用户信息数据库文件和组信息数据库文件纵向合并为一个文件/1.txt(覆盖) cat /etc/passwd /etc/group > /1.txt2) 将用户信息数据库文件和用户 ...