Java IO 教程

Java IO:FileReader 类

在 Java 的 I/O 体系中,FileReader 类(java.io.FileReader)的主要功能是把文件内容以字符流的形式进行读取。

FileReader 的工作原理和 FileInputStream 颇为相似,不过二者存在明显差异:FileInputStream 读取的是字节,而 FileReader 专注于读取字符。简单来讲,FileReader 就是专门为读取文本而设计的。要知道,一个字符可能对应一个或多个字节,这取决于具体的字符编码方案。

注意:FileReader 类继承自 Java 的 Reader 类,所以它拥有诸多和 Reader 类相同的方法。

FileReader 示例

以下是一个简单的 FileReader 示例:

package com.hxstrive.java_io;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class FileReaderExample {
    public static void main(String[] args) throws IOException {
        try(Reader reader = new FileReader("data.txt")) {
            int theCharNum = reader.read();
            while (theCharNum != -1) {
                char theChar = (char) theCharNum;
                System.out.print(theChar);
                theCharNum = reader.read();
            }
        }
        //输出:
        //你好!欢迎光临
    }
}

上述示例,首先创建了一个 FileReader,它直接连接到 FileReader 构造函数参数传递的文件路径指向的文件。其次,此示例从 FileReader 一次读取一个字符。最后,利用 Java7 的 try-with-resources 来自动关闭 FileReader。

read()

FileReader 的 read() 方法返回一个 int,其中包含读取字符的字符值。如果 read() 方法返回 -1,则表示 FileReader 中已无数据可读,则可以关闭了。例如:

try(Reader reader = new FileReader("data.txt")) {
    int theCharNum = reader.read(); // 读取数据
    while (theCharNum != -1) {
        char theChar = (char) theCharNum;
        System.out.print(theChar);
        theCharNum = reader.read(); // 读取数据
    }
}

上述示例仅从 FileReader 中读取字符,并未对这些字符做任何处理。

read(char[])

FileReader 也有一种方法可以读取字符数组,而不是一次读取一个字符。下面是一个将多个字符读入字符数组的示例:

FileReader fileReader = new FileReader("input.txt");
char[] destination = new char[1024]; // 字符数组
int charsRead = fileReader.read(destination, 0, destination.length);

上述示例中,read(char[]) 方法的第一个参数是要读入字符的字符数组,第二个参数是要写入字符的数组偏移量,第三个参数是要写入字符的最大长度。read(char[]) 方法返回实际读入字符数组的字符数。如果文件中的字符数少于您指定的最大字符数,那么读取的字符数将少于最大字符数。否则,read(char[]) 方法将尝试向数组中读取最大字符数。

注意:相较于通过 FileReader 一次读取一个字符,一次读取一个字符数组的速度要快得多。通过读取字符数组而非单个字符,性能轻松就能提升 10 倍甚至更多。

具体的速度提升幅度,取决于读取字符数组的大小,以及运行代码的计算机的操作系统、硬件等因素。在做决策前,你可以研究一下目标系统的硬盘缓冲区大小等参数。一般来说,8KB 及以上的缓冲区大小能带来不错的速度提升。不过,一旦字符数组大小超出了底层操作系统和硬件的承载能力,继续增大字符数组就无法再提高读取速度了。

你可以尝试使用不同大小的字节数组,并测量读取性能,从而找出最优的字符数组大小。

通过 BufferedReader 实现透明缓冲

借助 BufferedReader 类,能够为 FileReader 增添透明的缓冲功能。BufferedReader 会从底层 FileReader 批量读取大量字符,存入字符数组。随后,你可以逐个读取 BufferedReader 中的字符,这种方式同样能显著提升读取效率,充分发挥批量读取字符数组相较于逐个读取字符的速度优势。以下是使用 BufferedReader 封装 FileReader 的示例:

int bufferSize = 1024 * 8;
Reader input = new BufferedReader(new FileReader("input.txt"), bufferSize);

注意,BufferedReader 是 Reader 的子类,可在任何能使用 Reader 的地方使用。

FileReader 字符编码

FileReader 会默认采用应用程序运行所在计算机的默认字符编码,对文件中的字节进行解码。但这或许并非你所期望的,而且你还无法更改这一默认设置!

若你想指定其他字符解码方案,就别使用 FileReader 了,可在 FileInputStream 上搭配使用 InputStreamReader。借助 InputStreamReader,你能够自行指定在读取底层文件字节时所采用的字符编码方案。

关闭 FileReader

当从 FileReader 完成字符读取操作后,务必记得将其关闭。要关闭 FileReader,只需调用它的 close() 方法即可。以下为你展示关闭 Java FileReader 的具体步骤:

fileReader.close();

当然,你还可以使用 Java7 中引入的 try-with-resources 结构,让它自动帮你关闭资源,如下:

try(FileReader fileReader = new FileReader("text.txt")){
    int data = fileReader.read();
    while(data != -1) {
        System.out.print((char) data));
        data = fileReader.read();
    }
}

注意,上面示例中没有手动调用 close() 方法,而是让 try-with-resources 自动去调用 close() 方法。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号