粮草机器人 在 Windows 操作系统下使用 JDK 8 时,FileReader 是 Java IO 包中用于读取字符文件的便捷类

在 Windows 操作系统下使用 JDK 8 时,FileReader 是 Java IO 包中用于读取字符文件的便捷类。

以下是对 FileReader 的源码结构、工作原理及具体使用方法的详细分析。


1. FileReader 源码结构与继承关系


FileReader 本身是一个非常轻量的类,它并没有实现复杂的读取逻辑,而是通过继承体系复用父类的功能。


继承 hierarchy

java

public class FileReader extends InputStreamReader


直接父类‌:InputStreamReader(字节流到字符流的桥梁)。

间接父类‌:Reader(所有字符输入流的抽象基类)。

实现接口‌:Closeable, AutoCloseable, Readable。

核心源码分析(JDK 8)


在 JDK 8 中,FileReader 的主要代码仅包含几个构造方法。其核心逻辑在于构造时内部创建了一个 FileInputStream,并将其传递给父类 InputStreamReader。


java

package java.io;


import java.nio.charset.Charset;


public class FileReader extends InputStreamReader {


    // 构造方法 1:通过文件路径字符串创建

    public FileReader(String fileName) throws FileNotFoundException {

        super(new FileInputStream(fileName));

    }


    // 构造方法 2:通过 File 对象创建

    public FileReader(File file) throws FileNotFoundException {

        super(new FileInputStream(file));

    }


    // 构造方法 3:通过文件描述符创建

    public FileReader(FileDescriptor fd) {

        super(new FileInputStream(fd));

    }

}



关键点解析:‌


本质是字节流转换‌:FileReader 内部持有一个 FileInputStream 实例。它先以字节形式从硬盘读取数据,然后通过 InputStreamReader 将字节解码为字符。

默认编码陷阱‌:注意上述构造方法中,调用 super(...) 时‌没有指定字符集‌。这意味着它使用‌平台默认字符集进行解码‌。

在 ‌Windows‌ 系统上,JDK 8 的默认字符集通常是 ‌GBK‌ (或 GB2312/CP936)。

如果读取的文件是 UTF-8 编码,而系统默认是 GBK,直接使用 FileReader 会导致‌中文乱码‌。

2. 主要使用方法


由于 FileReader 继承了 InputStreamReader 和 Reader,它可以使用以下核心方法读取数据:


表格

方法签名 说明

int read() 读取单个字符,返回字符的 Unicode 值,到达流末尾返回 -1。

int read(char[] cbuf) 将字符读入数组,返回读取的字符数,到达末尾返回 -1。

int read(char[] cbuf, int off, int len) 将字符读入数组的一部分,效率较高,推荐用于大文件。

void close() 关闭流并释放资源。

3. 代码示例

示例 1:基础读取(逐个字符)


适用于小文件或测试,效率较低。


java

import java.io.FileReader;

import java.io.IOException;


public class FileReaderDemo1 {

    public static void main(String[] args) {

        // 假设 test.txt 是 GBK 编码(Windows 默认新建文本文件通常为 ANSI/GBK)

        FileReader fr = null;

        try {

            fr = new FileReader("test.txt");

            int ch;

            // read() 返回 int,需要强转为 char 才能显示正确字符

            while ((ch = fr.read()) != -1) {

                System.out.print((char) ch);

            }

        } catch (IOException e) {

            e.printStackTrace();

        } finally {

            if (fr != null) {

                try {

                    fr.close();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        }

    }

}


示例 2:高效读取(字符数组缓冲)


推荐方式,减少 IO 次数。


java

import java.io.FileReader;

import java.io.IOException;


public class FileReaderDemo2 {

    public static void main(String[] args) {

        FileReader fr = null;

        try {

            fr = new FileReader("test.txt");

            char[] buffer = new char; // 1KB 缓冲区

            int len;

            while ((len = fr.read(buffer)) != -1) {

                // 注意:只打印实际读取到的长度,避免打印缓冲区残留数据

                System.out.print(new String(buffer, 0, len));

            }

        } catch (IOException e) {

            e.printStackTrace();

        } finally {

            try {

                if (fr != null) fr.close();

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

    }

}


示例 3:使用 try-with-resources(JDK 7+ 推荐)


自动管理资源关闭,代码更简洁安全。


java

import java.io.FileReader;

import java.io.IOException;


public class FileReaderDemo3 {

    public static void main(String[] args) {

        // try 括号内声明的资源会在 try 块结束后自动关闭

        try (FileReader fr = new FileReader("test.txt")) {

            char[] buffer = new char;

            int len;

            while ((len = fr.read(buffer)) != -1) {

                System.out.print(new String(buffer, 0, len));

            }

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}


4. Windows 环境下的关键注意事项

1. 编码乱码问题


这是 FileReader 在 Windows 上最大的痛点。


现象‌:如果文件是用 UTF-8 保存的(例如现代编辑器默认格式),而你在 Windows JDK 8 上使用 new FileReader("utf8_file.txt"),读取出的中文会变成乱码。

原因‌:FileReader 强制使用 Charset.defaultCharset(),Windows 下通常为 GBK。

解决方案‌:如果需要指定编码(如 UTF-8),‌不要直接使用 FileReader‌,而应使用 InputStreamReader 包装 FileInputStream:

java

// 正确读取 UTF-8 文件的方式

try (InputStreamReader isr = new InputStreamReader(

        new FileInputStream("utf8_file.txt"), "UTF-8")) {

    // 使用 isr 进行读取...

}


2. 换行符处理

Windows 系统的换行符是 \r\n。

FileReader 的 read() 方法会原样读取这些字符。如果你逐字符读取并打印,可能会看到额外的空行或控制字符行为,具体取决于控制台如何处理 \r。通常使用 BufferedReader 包装 FileReader 并使用 readLine() 可以屏蔽不同操作系统的换行差异。

3. 文件路径

在 Windows 上,文件路径分隔符可以是 \ 或 /。但在 Java 字符串中,反斜杠 \ 需要转义为 \\。

推荐使用正斜杠 / 或 File.separator 以保证跨平台兼容性,尽管在纯 Windows 环境下 \ 也能工作。

总结

适用场景‌:FileReader 适合读取‌已知编码与平台默认编码一致‌(在 Windows 上即 GBK/ANSI)的文本文件。

不适用场景‌:读取二进制文件(图片、视频等)应使用 FileInputStream;读取非平台默认编码(如 UTF-8)的文本文件,建议使用 InputStreamReader + FileInputStream 组合。

最佳实践‌:始终配合 BufferedReader 使用以提高效率,并使用 try-with-resources 确保资源释放。