Java IO流的分类
Java IO流主要从两个维度分类:
| 分类维度 |
分类结果 |
说明 |
| 按数据流向分 |
输入流(Input) |
从磁盘/网络/内存「读」数据到程序 |
|
输出流(Output) |
从程序「写」数据到磁盘/网络/内存 |
| 按处理单元分 |
字节流(Byte Stream) |
以「字节(byte)」为单位处理数据,是万能流 |
|
字符流(Character Stream) |
以「字符(char)」为单位处理数据,专门处理文本 |
字节流
什么是字节流?
计算机里所有数据(图片、视频、音频、文本、PDF)本质上都是字节(0和1的组合),所以字节流是万能流,可以处理任何类型的数据。
字节流的核心类
字节流的抽象基类是 InputStream(输入流)和 OutputStream(输出流),开发中最常用的是它们的子类:
| 类名 |
作用 |
FileInputStream |
从文件中读取字节 |
FileOutputStream |
向文件中写入字节 |
BufferedInputStream |
带缓冲的字节输入流,提升读性能 |
BufferedOutputStream |
带缓冲的字节输出流,提升写性能 |
举个例子
字节流典型的应用——复制非文本文件(图片、视频、PDF)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteStreamExample {
public static void main(String[] args) {
// 源文件路径(一张图片)
String srcPath = "C:/test/photo.jpg";
// 目标文件路径
String destPath = "C:/test/photo_copy.jpg";
// 用try-with-resources自动关闭流,避免内存泄漏
try (
// 1. 创建文件字节输入流:从源文件读字节
FileInputStream fis = new FileInputStream(srcPath);
// 2. 创建文件字节输出流:向目标文件写字节
FileOutputStream fos = new FileOutputStream(destPath)
) {
// 3. 定义一个字节数组作为缓冲区(一次读1024字节,即1KB,提升性能)
byte[] buffer = new byte[1024];
int len; // 记录每次实际读到的字节数
// 4. 循环读写:fis.read(buffer)返回-1表示读到文件末尾
while ((len = fis.read(buffer)) != -1) {
// 只写实际读到的len个字节,避免最后一次写多余的空字节
fos.write(buffer, 0, len);
}
System.out.println("图片复制成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
|
字符流
什么是字符流?
字符流是专门处理文本数据的流,它以【字符】为单位处理数据,内部会自动处理编码转换(比如把UTF-8编码的字节转成Java的char字符)。
为什么不用字节流处理文本?
因为中文等非ASCII字符占多个字节(比如UTF-8编码的中文占3个字节)。
如果用字节流读,可能会把一个汉字的3个字节截断,从而导致乱码;
而字符流会自动识别编码,按字符读取,不会乱码。
字符流的核心类
字符流的抽象基类是 Reader(输入流)和 Writer(输出流),开发中最常用的是它们的子类:
| 类名 |
作用 |
FileReader |
从文件中读取字符 |
FileWriter |
向文件中写入字符 |
BufferedReader |
带缓冲的字符输入流 |
BufferedWriter |
带缓冲的字符输出流 |
InputStreamReader |
转换流:字节流转字符流 |
OutputStreamWriter |
转换流:字符流转字节流 |
举个例子
BufferedReader的readLine()方法可以按行读取文本,非常方便。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class CharacterStreamExample {
public static void main(String[] args) {
String filePath = "C:/test/中文文章.txt";
// 用转换流InputStreamReader,显式指定UTF-8编码,避免乱码
try (
// 1. 先创建字节输入流
FileInputStream fis = new FileInputStream(filePath);
// 2. 用转换流把字节流转成字符流,显式指定UTF-8编码
InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
// 3. 用缓冲流包装,提升性能,且有readLine()方法
BufferedReader br = new BufferedReader(isr)
) {
String line;
int lineNum = 1;
// readLine()返回null表示读到文件末尾
while ((line = br.readLine()) != null) {
System.out.println("第" + lineNum + "行:" + line);
lineNum++;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
|