主要区别
- 处理单元不同:
- 字节流:以字节(8位二进制数据)为单位进行数据处理。
InputStream
和OutputStream
是字节流的抽象基类。例如,在读取图片、音频、视频等二进制文件时,字节流按字节逐个读取或写入这些文件的数据。
- 字符流:以字符(16位Unicode数据)为单位进行数据处理。
Reader
和Writer
是字符流的抽象基类。字符流会根据指定的字符编码(如UTF - 8、GBK等)将字节转换为字符。例如,在处理文本文件时,字符流可以方便地按字符读取和写入文本内容,处理中文字符等多字节字符时能正确解析。
- 处理方式不同:
- 字节流:直接操作二进制数据,不关心数据的具体含义。比如在网络通信中,发送和接收的数据一般使用字节流,因为网络传输的数据本质上是字节序列,字节流能直接对这些字节进行处理。
- 字符流:在字节流的基础上,增加了对字符编码的处理。它可以根据字符编码将字节转换为字符,或者将字符转换为字节。例如在读取文本文件时,字符流可以根据文件的编码格式(如UTF - 8)正确地将字节转换为字符,方便对文本内容进行处理。
- 缓冲区实现不同:
- 字节流:字节流的缓冲区实现类是
BufferedInputStream
和BufferedOutputStream
,它们以字节为单位进行缓冲。例如在读取大文件时,使用BufferedInputStream
可以减少磁盘I/O操作的次数,提高读取效率,它每次从磁盘读取一定数量的字节到缓冲区中。
- 字符流:字符流的缓冲区实现类是
BufferedReader
和BufferedWriter
,它们以字符为单位进行缓冲。在处理文本时,BufferedReader
可以一次读取一行文本,这是基于字符的缓冲操作,比字节流按字节读取一行文本更高效。
优先选择场景
- 优先选择字符流的场景:
- 文本处理:例如读取和写入文本文件(.txt、.java等)。如下代码读取一个文本文件内容:
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
- 网络通信中的文本传输:比如在HTTP协议中传输HTML、JSON等文本数据。在Java的
HttpURLConnection
获取响应数据时,如果响应内容是文本类型,可以使用字符流处理。
try (BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()))) {
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
System.out.println(response.toString());
} catch (IOException e) {
e.printStackTrace();
}
- 优先选择字节流的场景:
- 处理二进制文件:如图片、音频、视频文件。以下代码实现复制一个图片文件:
try (InputStream inputStream = new FileInputStream("source.jpg");
OutputStream outputStream = new FileOutputStream("destination.jpg")) {
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
}
- 网络通信中的二进制数据传输:如在Socket通信中传输自定义的二进制协议数据,字节流能直接处理这些二进制数据,不需要进行字符编码转换等额外操作。
try (Socket socket = new Socket("localhost", 12345);
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream()) {
byte[] data = "Hello, Server!".getBytes();
outputStream.write(data);
byte[] buffer = new byte[1024];
int length = inputStream.read(buffer);
System.out.println("Received: " + new String(buffer, 0, length));
} catch (IOException e) {
e.printStackTrace();
}