使用BufferedReader读取文章_java按行读取文件_java读取文件方法

Java编程里,读取文件属于极为基础且极为常见的操作当中的一项,然而好多开发者对于不同情景之下应当选用哪一种读取方式依旧心存困惑,倘若选错方法则极有可能致使程序性能下降至于数十倍之多,甚至还会引发内存溢出。

基于字符流的经典读取

字节流到字符流的转换桥梁

InputStreamReader担当起从字节流转化至字符流的角色,它针对字节予以读取,并且把那些字节解码成字符。

建立InputStreamReader之际,我们能够指定字符编码,像UTF - 8或者GBK,这对如实处理含有中文等多字节字符的文本文件来讲极为关键。

要是没有明确地去指定那种编码,那么构造方法就会采用操作系统默认的编码,而这样子会致使程序在不同的平台之间进行移植的时候出现乱码的问题。

带缓冲的性能优化方案

仅仅是直接运用FileReader去读取文件之际,于每一次调用read()方法之时,都会引发底层操作系统开展一回磁盘访问,如此这般频繁的IO操作将会是极度低效的。

BufferedReader借助在其内部维持一个8192字符的缓冲区,从而明显地削减了实际IO操作的频次。

其readLine()方法给出了按行读取的便利特性,能够自动辨别不同操作系统的换行符,像是Linux的n或者Windows的rn。

基于Scanner的解析式读取

正则表达式驱动的分词器

Scanner类在里层运用正规表达式去辨别不一样类型数据模式,如此一来它就可以机灵地把文本流划分成为标记序列。

此时,当着 Scanner 调用 nextInt() 方法之际 ,再者或者调用 nextDouble() 方法之时 ,它会自动地 ,去跳过空白字符 ,进而寻找到下一个 ,符合数值格式的标记 ,并且对其进行转换。

try {

FileReader reader = new FileReader("article.txt");

BufferedReader bufferedReader = new BufferedReader(reader);

String line;

while ((line = bufferedReader.readLine()) != null) {

System.out.println(line);

}

bufferedReader.close();

} catch (IOException e) {

e.printStackTrace();

}

能力是这种解析,它让处理配置文件变得异常简单,此配置文件包含的是混合数据类型。

灵活的分隔符设置机制

Scanner 默认是以空白字符当作分隔符处理的,然而我们能够借助 useDelimiter () 方法去自行定义分隔符样式。

像是在针对CSV文件加以处理之际,能够把分隔符设定成逗号;于处理日志文件之时,可以设置为由空格加上冒号而形成的组合的呢。

这种灵活性使得Scanner成为用于处理各类格式文本文件的理想工具,特别是适宜于处理结构并非十分复杂的配置文件。

基于NIO的通道式读取

通道与缓冲区的协同工作

Java NIO之中,引入了通道以及缓冲区这两个核心概念,通道它所代表的是到实体的开放连接,借助这个连接能够实现高效的数据传输,又有缓冲区它是作为存储数据的容器而存在。

FileChannel的read()方法,是把数据从通道读入到缓冲区之中,而write()方法,情况截然,不同,是把数据从缓冲区写回到通道,与read()方法相反。

这样的设计,使得数据传输朝着操作系统级别更靠近,躲开了来自Java堆内存跟本地内存之间的多次数据拷贝。

try {

File file = new File("article.txt");

Scanner scanner = new Scanner(file);

while (scanner.hasNextLine()) {

String line = scanner.nextLine();

System.out.println(line);

}

scanner.close();

} catch (FileNotFoundException e) {

e.printStackTrace();

}

内存映射文件的极致性能

FileChannel的map()方法是有这样的作用的,它可完成把文件区域朝着内存当中进行直接映射这个行为,之后会返回出一个MappedByteBuffer对象。

采用这样的方法,文件数据好像如同处于内存里那般,应用程序能够径直借助对内存地址加以操作来实现读写文件。

尤为高效的是这种针对大文件处理的方法,其避免了传统方式下用户空间与内核空间之间的数据拷贝,达成了零拷贝技术。

基于Files工具类的便捷读取

一次性读取全部内容

Files类里边的readAllLines()这个方法,以及readString()这个方法,于处理小型文本文件之方面,提供了极大程度的便利。

当使用readAllLines()方法时,它会返回一个字符串所构成的列表,其中每一行都对应着列表里的一个元素,并且该方法能够自动对字符编码的问题进行处理。

对呀,针对配置文件或者小数据量的文本处理情形而言,这般一行代码便能够达成文件读取的运作方式,不但代码是简洁的,并且不容易出现错误呢。

流式处理的新范式

try {

Path path = Paths.get("article.txt");

List lines = Files.readAllLines(path, StandardCharsets.UTF_8);

for (String line : lines) {

System.out.println(line);

}

} catch (IOException e) {

e.printStackTrace();

}

Files.lines()方法返回一个对象,该对象是Stream类型,这让我们能够借助函数式编程风格去处理文件内容。

通过结合lambda表达式,我们能够轻易地实现复杂操作,诸如过滤,映射,归约等。

面对那种需要针对文件内容开展复杂转换工作的情形,流式处理是十分适配的状况,而且它还具备支持并行处理的能力,能够将多核处理器所拥有的性能优势予以充分利用。

不同场景下的选型建议

文件大小的决定性因素

针对那些比10MB小的小文件而言,选用Files.readAllLines()这种方式算是最为简单直接的一种选择了。

若是针对中等尺寸大小的文件,当存在需要进行逐行予以处理的情况时,BufferedReader于代码的可读性与性能之间达成了不错的平衡状态。

文件大小一旦超过100MB,便应当考量运用NIO的通道或者内存映射方式,防止因一次性加载整个文件而致使内存溢出。

内容格式的决定性影响

处理简单文本文件时,BufferedReader足够胜任。

去处理那包含着多种数据类型的结构化文件之际,Scanner所具备的解析能力,是那种无可替代的优势。

像是读取大型日志文件里特定时间段的数据这种,属于需要随机访问文件内容的场景,在此种场景下,RandomAccessFile配合NIO 通道它就是最合适的选择。

异常处理与资源管理

try-with-resources自动关闭

Java 7所引入的try-with-resources语句,做到了确保,每个资源,于语句结束之际,能够自动关闭。

这种语法可应用于所有实现了AutoCloseable接口的IO类,这不但使代码得到简化,更要紧的是防止了因忘掉关闭资源致使的内存泄漏以及文件句柄泄漏。

在文件读取操作中,正确关闭资源与正确编写读取逻辑同样重要。

字符编码问题的最佳实践

操作系统不一样,默认编码也不一样,Windows采用GBK编码,Linux采用UTF - 8编码,这致使跨平台应用里常常出现乱码状况。

最棒的实践做法是,于全部的读取操作里面,去明确地指定字符编码,就好像StandardCharsets.UTF_8那样。

如此进行操作,不但确保了程序行为具备一致性,还展现出良好的编程习惯,防止了因环境存在差异而致使难以开展排查工作的bug。

你于实际开展开发期间,有没有碰见过,由于文件读取方式选取得不恰当,进而引发的性能方面的问题呢?

欢迎于评论区域分享自身的经验以及教训,动用点赞操作并收藏此文本,从而能够随时进行查阅这些具备实用性的读取技巧。