【Java】字符流详解
大家好,本篇继续更新Java IO系列内容,在上一篇讲解完字节流之后,今天带大家系统学习Java中的字符流。字节流适合处理图片、视频等二进制文件,而日常开发中接触最多的文本文件,用字符流处理会更加便捷,还能完美规避编码乱码问题。
一、字符流与字节流的核心区别
Java IO流分为两大体系:字节流(InputStream/OutputStream) 和字符流(Reader/Writer)。
- 字节流:以字节为单位读写,通用型流,可处理所有类型文件(图片、音视频、文档等)。
- 字符流:以字符为单位读写,专门用于文本数据,底层本质还是字节流,额外封装了编码表。
简单总结一句话:字符流 = 字节流 + 字符编码表。常用编码有UTF-8、GBK、ASCII等,这也是字符流能自动完成字节与字符转换的核心原因。
二、字符输入流 Reader
java.io.Reader 是所有字符输入流的顶层抽象父类,定义了读取字符的通用方法,我们日常最常用的实现类是 FileReader,专门用来读取本地文本文件。
1. Reader 通用核心方法
int read():读取单个字符,读到文件末尾返回-1;int read(char[] cbuf):读取多个字符存入字符数组,返回实际读取的字符个数;void close():关闭流,释放系统资源。
2. FileReader 构造方法
FileReader(File file):传入File对象创建读取流;FileReader(String fileName):传入文件路径字符串创建读取流。
3. 代码示例:读取文本文件
方式1:单个字符读取
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo {
public static void main(String[] args) {
// 定义文件路径
String filePath = "test.txt";
try (FileReader fr = new FileReader(filePath)) {
int ch;
// 循环读取单个字符,末尾返回-1结束循环
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
方式2:字符数组批量读取(效率更高)
实际开发推荐使用数组读取,减少IO交互,提升性能:
import java.io.FileReader;
import java.io.IOException;
public class FileReaderArrayDemo {
public static void main(String[] args) {
String filePath = "test.txt";
try (FileReader fr = new FileReader(filePath)) {
// 定义字符数组作为缓冲区
char[] buf = new char[1024];
int len;
// len为本次实际读取的字符数量
while ((len = fr.read(buf)) != -1) {
System.out.print(new String(buf, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
三、字符输出流 Writer
java.io.Writer 是所有字符输出流的顶层抽象父类,常用实现类为 FileWriter,用于向本地文本文件写入字符数据。
1. Writer 通用核心方法
write(int c):写入单个字符;write(char[] cbuf):写入整个字符数组;write(char[] cbuf, int off, int len):写入字符数组的指定区间;write(String str):直接写入字符串(字符流独有便捷方法);flush():刷新缓冲区;close():关闭流(关闭前会自动刷新缓冲区)。
2. FileWriter 构造方法
FileWriter(File file)/FileWriter(String fileName):覆盖写入,原有文件内容会被清空;FileWriter(String fileName, boolean append):第二个参数为true,表示续写,不覆盖原有内容。
3. 代码示例:写入文本文件
基础写入、换行与续写
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterDemo {
public static void main(String[] args) {
String filePath = "output.txt";
try (FileWriter fw = new FileWriter(filePath, true)) {
// 写入字符串
fw.write("Java字符流学习");
// 换行(Windows系统换行符 \r\n)
fw.write("\r\n");
// 写入单个字符
fw.write('A');
fw.write("\r\n");
// 写入字符数组
char[] chars = {'1','2','3','4'};
fw.write(chars);
// 手动刷新缓冲区(close方法也会自动刷新)
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
四、flush 与 close 的区别
这是字符流高频考点,很多新手容易混淆:
- flush():只刷新内存缓冲区,把缓冲区数据强制写入文件,流对象可以继续使用;
- close():先执行一次
flush()刷新缓冲区,再关闭流、释放系统资源,流对象无法再使用。
小贴士:字符流自带缓冲区,如果不调用
flush()或close(),数据会一直停留在缓冲区,不会真正写入文件。
五、实战:使用字符流复制文本文件
结合FileReader和FileWriter,完成标准文本文件复制,注意:字符流不适合复制图片、视频等非文本文件。
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyTextFile {
public static void main(String[] args) {
// 源文件路径、目标文件路径
String srcPath = "source.txt";
String destPath = "target.txt";
// try-with-resources 自动关闭流,简化异常处理
try (FileReader fr = new FileReader(srcPath);
FileWriter fw = new FileWriter(destPath)) {
char[] buf = new char[1024];
int len;
// 边读边写
while ((len = fr.read(buf)) != -1) {
fw.write(buf, 0, len);
}
System.out.println("文本文件复制完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
六、IO 异常处理方式
上面示例中我使用了 try-with-resources,这是JDK7之后推荐的写法,会自动实现流的关闭,代码更简洁。
传统写法(try...catch...finally)参考:
import java.io.FileReader;
import java.io.IOException;
public class IoExceptionDemo {
public static void main(String[] args) {
FileReader fr = null;
try {
fr = new FileReader("test.txt");
int ch;
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// finally 中保证流一定关闭
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
七、总结
- 字符流(
Reader/Writer)专为文本文件设计,底层依托字节流+编码表,解决中文乱码问题; - 核心实现类:文件读取
FileReader、文件写入FileWriter; - 操作规范:字符流必须注意缓冲区,使用完毕及时
flush或close; - 适用场景区分:文本文件优先字符流,二进制文件(图片、视频等)必须使用字节流;
- 异常处理优先使用
try-with-resources,简化代码并规避资源泄漏问题。
到此Java基础字符流的知识点就讲解完毕了,下一期我会继续分享IO流中的缓冲字符流,进一步提升读写效率,感兴趣的朋友可以持续关注~



