持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
前言
明天就放假了兄弟们,大家都有什么计划呀?放松当然也是要放松的,但是希望我可以在空闲时间把最近做的这些需求整理好记录一下吧!简要概述需求就是:按行读取文件内容,对每一行的数据进行处理!上一篇文章记录了如何获取到每一个文件的绝对路径;今天记录一下如何按行读取数据量很大的文件,总共学习了两种方法,今天先记录一下其中的一种 :BufferedReader;
代码
这一段代码,在我测试的时候处理有70万行的数据的文件时运行良好,大家可以按需修改;领导说用list接收行内容不合适,这个我现在也还有疑问
// 按行读取文件,并截取数据存入list
public static List<String> readThread(String filePath){
long start = System.currentTimeMillis();
LOG.info("按行读取文件,并截取数据开始>>>>>>>>>>>>>>" + LocalDateTime.now().toString() );
List<String> list = new ArrayList<>();
try {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
BufferedReader in = new BufferedReader(new InputStreamReader(bis, "utf-8"), 10 * 1024 * 1024);//10M缓存
String tempString;
while ((tempString = in.readLine()) != null) {
if(tempString.indexOf(",") != -1 && tempString.indexOf(",") > 14){
list.add(tempString.substring(tempString.indexOf(",")-14));
}else if(tempString.indexOf(",") == 14){
list.add(tempString);
}
// 在这里处理行数据 String line = in.readLine();
}
in.close();
long end = System.currentTimeMillis();
LOG.info("按行读取文件,并截取数据完成,耗时:" + (end - start) + " ms");
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
详解
流
概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成。
分类 按照流向分为:输入流和输出流;按照传输单位分为:字符流和字节流;
FileInputStream
它被称为文件字节输入流,意思指对文件数据以字节的形式进行读取操作;查看对应的源码如下:
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
BufferedInputStream
BufferedInputStream是一个带有缓冲区的输入流,通常使用它可以提高我们的读取效率。
原理:
BufferedInputStream内部有一个缓冲区,每次调用read方法的时候,它首先尝试从缓冲区里读取数据,若读取失败(缓冲区无可读数据),则选择从物理数据源(譬如文件)读取新数据(这里会尝试尽可能读取多的字节)放入到缓冲区中,最后再将缓冲区中的内容部分或全部返回给用户.由于从缓冲区里读取数据远比直接从物理数据源(譬如文件)读取速度快,所以BufferedInputStream的效率很高!
InputStreamReader
类 InputStreamReader是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。 为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:
BufferedReader in= new BufferedReader(new InputStreamReader(bis));
readLine()
Java中BufferedReader类的readLine()方法用于一次读取一行文本。行尾应以'\ n'或'\ r'或EOF来理解。
参数: 此方法不接受任何参数。
返回值: 此方法返回此方法读取的String,并排除任何可用的终止符号。如果缓冲的流已经结束并且没有要读取的行,则此方法返回NULL。
异常: 如果发生I /O错误,则此方法将引发IOException。
综述
整体意思就是用InputStreamReader这个中介把FileInputStream这个字节流转换成字符流BufferedReader,再调用BufferedReader 对象的readLine()方法读取文件的每一行;
总结
这个按行读取大文件的方法,领导评审的时候说BufferedReader在读几次之后效率就会变得慢,性能不友好;可能是我测试的数据量比较小吧,没有明显的体会;领导说读出来的每行数据用list接收不合适,提了一嘴list的最大存储量是65535,但是我测试的时候70万条数据也没有报错呀?所以还是很疑惑的。