基于本文回答
0
评论

Java 中节流(Byte Stream)和字符流(Character Stream)有什么区别

在 Java 的 I/O 流中,你提到的“节流”应该是笔误,实际对应的是字节流(Byte Stream)。它与字符流(Character Stream)是 Java 输入输出系统的两大核心分类。

它们的核心区别在于处理数据的最小单位以及适用的场景。以下是详细的对比分析:


1. 核心区别对比

特性 字节流 (Byte Stream) 字符流 (Character Stream)
处理单位 8 位(1个字节,1 Byte) 16 位(2个字节/Unicode 字符)
基类(输入/输出) InputStream / OutputStream Reader / Writer
处理的数据类型 所有类型的文件(二进制文件如图片、视频、音频、PDF、ZIP,以及文本文件) 仅文本数据(如 .txt, .html, .json 等)
缓冲区 (Buffer) 默认不使用缓冲区(直接操作文件),但可以通过包装流(如 BufferedInputStream)来使用。 默认使用内存缓冲区。写入时必须刷新(flush)或关闭(close)才能将数据真正写入目的地。
字符集编码 不涉及字符编码转换,只负责原封不动地搬运字节。 自动处理字符编码(如 UTF-8, GBK)。会根据指定的字符集将字节解码为字符。

2. 为什么需要字符流?(根本原因)

在计算机中,所有数据本质上都是字节(0和1)。

  • 如果用字节流读取一个中文文本,而中文在 UTF-8 编码下占用 3 个字节:
    • 如果你每次只读取 1 个字节,就会把一个汉字拆散,导致输出时出现乱码
  • 字符流的出现就是为了解决这个难题。它内部集成了编码表(Charset),能够自动识别一个字符占用几个字节(比如遇到中文就一次性读取3个字节,拼成一个完整的字符),从而避免乱码。

3. 代码示例对比

示例 1:使用字节流复制文件(图片、视频等)

字节流适合处理任何文件,包括二进制文件。

java
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ByteStreamDemo {
    public static void main(String[] args) {
        // 复制一张图片
        try (FileInputStream fis = new FileInputStream("input.jpg");
             FileOutputStream fos = new FileOutputStream("output.jpg")) {
            
            int byteData;
            // 每次读取一个字节
            while ((byteData = fis.read()) != -1) {
                fos.write(byteData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

示例 2:使用字符流读取文本文件

字符流适合处理含有中文等各种字符的文本文件。

java
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CharStreamDemo {
    public static void main(String[] args) {
        // 复制文本文件(含中文)
        try (FileReader reader = new FileReader("input.txt");
             FileWriter writer = new FileWriter("output.txt")) {
            
            int charData;
            // 每次读取一个字符(会自动处理多字节的汉字)
            while ((charData = reader.read()) != -1) {
                writer.write(charData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4. 转换流(桥梁)

有时候我们需要在字节流和字符流之间进行转换。Java 提供了两个转换流,它们是字符流的子类:

  • InputStreamReader:将字节输入流转换为字符输入流(读文件时,将磁盘上的字节转为内存中的字符)。
  • OutputStreamWriter:将字符输出流转换为字节输出流(写文件时,将内存中的字符转为磁盘上的字节)。

经典用法(指定编码读取文本):

java
// 以 UTF-8 编码读取一个文本文件
BufferedReader reader = new BufferedReader(
    new InputStreamReader(new FileInputStream("test.txt"), "UTF-8")
);

5. 如何选择?(开发建议)

  1. 如果是音频、视频、图片、可执行文件(.exe)等非文本文件: 必须使用字节流
  2. 如果是纯文本文件(.txt, .java, .xml, .html等): 优先使用字符流,因为效率更高,且不会产生乱码。
  3. 如果不确定文件类型: 使用字节流,因为它是万能的。
右滑查看面试常问