【Java】字符流详解

大家好,本篇继续更新Java IO系列内容,在上一篇讲解完字节流之后,今天带大家系统学习Java中的字符流。字节流适合处理图片、视频等二进制文件,而日常开发中接触最多的文本文件,用字符流处理会更加便捷,还能完美规避编码乱码问题。

一、字符流与字节流的核心区别

Java IO流分为两大体系:字节流(InputStream/OutputStream)字符流(Reader/Writer)

  • 字节流:以字节为单位读写,通用型流,可处理所有类型文件(图片、音视频、文档等)。
  • 字符流:以字符为单位读写,专门用于文本数据,底层本质还是字节流,额外封装了编码表。

简单总结一句话:字符流 = 字节流 + 字符编码表。常用编码有UTF-8、GBK、ASCII等,这也是字符流能自动完成字节与字符转换的核心原因。

二、字符输入流 Reader

java.io.Reader 是所有字符输入流的顶层抽象父类,定义了读取字符的通用方法,我们日常最常用的实现类是 FileReader,专门用来读取本地文本文件。

1. Reader 通用核心方法

  1. int read():读取单个字符,读到文件末尾返回 -1
  2. int read(char[] cbuf):读取多个字符存入字符数组,返回实际读取的字符个数;
  3. 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 通用核心方法

  1. write(int c):写入单个字符;
  2. write(char[] cbuf):写入整个字符数组;
  3. write(char[] cbuf, int off, int len):写入字符数组的指定区间;
  4. write(String str):直接写入字符串(字符流独有便捷方法);
  5. flush():刷新缓冲区;
  6. 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 的区别

这是字符流高频考点,很多新手容易混淆:

  1. flush():只刷新内存缓冲区,把缓冲区数据强制写入文件,流对象可以继续使用
  2. close():先执行一次flush()刷新缓冲区,再关闭流、释放系统资源,流对象无法再使用

小贴士:字符流自带缓冲区,如果不调用flush()close(),数据会一直停留在缓冲区,不会真正写入文件。

五、实战:使用字符流复制文本文件

结合FileReaderFileWriter,完成标准文本文件复制,注意:字符流不适合复制图片、视频等非文本文件

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();
                }
            }
        }
    }
}

七、总结

  1. 字符流(Reader/Writer)专为文本文件设计,底层依托字节流+编码表,解决中文乱码问题;
  2. 核心实现类:文件读取FileReader、文件写入FileWriter
  3. 操作规范:字符流必须注意缓冲区,使用完毕及时flushclose
  4. 适用场景区分:文本文件优先字符流,二进制文件(图片、视频等)必须使用字节流;
  5. 异常处理优先使用try-with-resources,简化代码并规避资源泄漏问题。

到此Java基础字符流的知识点就讲解完毕了,下一期我会继续分享IO流中的缓冲字符流,进一步提升读写效率,感兴趣的朋友可以持续关注~

Tags:

发表回复

Your email address will not be published. Required fields are marked *.

*
*