引言

IO流是Java处理输入输出的核心API。本文系统讲解Java IO流的使用方法。

一、IO流分类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
字节流
├── InputStream(输入)
│ ├── FileInputStream
│ ├── BufferedInputStream
│ └── ObjectInputStream
└── OutputStream(输出)
├── FileOutputStream
├── BufferedOutputStream
└── ObjectOutputStream

字符流
├── Reader(输入)
│ ├── FileReader
│ ├── BufferedReader
│ └── InputStreamReader
└── Writer(输出)
├── FileWriter
├── BufferedWriter
└── OutputStreamWriter

二、字节流

2.1 FileInputStream和FileOutputStream

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 读取文件
try (FileInputStream fis = new FileInputStream("input.txt")) {
int data;
while ((data = fis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}

// 写入文件
try (FileOutputStream fos = new FileOutputStream("output.txt")) {
String content = "Hello, World!";
fos.write(content.getBytes());
} catch (IOException e) {
e.printStackTrace();
}

2.2 BufferedInputStream和BufferedOutputStream

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 带缓冲的读取(效率更高)
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("input.txt"))) {
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, len));
}
}

// 带缓冲的写入
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("output.txt"))) {
bos.write("Hello".getBytes());
bos.flush(); // 刷新缓冲区
}

三、字符流

3.1 FileReader和FileWriter

1
2
3
4
5
6
7
8
9
10
11
12
// 读取文本文件
try (FileReader reader = new FileReader("input.txt")) {
int data;
while ((data = reader.read()) != -1) {
System.out.print((char) data);
}
}

// 写入文本文件
try (FileWriter writer = new FileWriter("output.txt")) {
writer.write("Hello, World!");
}

3.2 BufferedReader和BufferedWriter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 按行读取
try (BufferedReader br = new BufferedReader(
new FileReader("input.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}

// 按行写入
try (BufferedWriter bw = new BufferedWriter(
new FileWriter("output.txt"))) {
bw.write("Line 1");
bw.newLine();
bw.write("Line 2");
}

四、转换流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// InputStreamReader:字节流转字符流
try (InputStreamReader isr = new InputStreamReader(
new FileInputStream("input.txt"), "UTF-8")) {
int data;
while ((data = isr.read()) != -1) {
System.out.print((char) data);
}
}

// OutputStreamWriter:字符流转字节流
try (OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("output.txt"), "UTF-8")) {
osw.write("Hello, 世界!");
}

五、对象流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 对象序列化
class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;

// 构造器、getter、setter
}

// 写入对象
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("person.dat"))) {
Person person = new Person("Alice", 25);
oos.writeObject(person);
}

// 读取对象
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("person.dat"))) {
Person person = (Person) ois.readObject();
System.out.println(person);
}

六、文件操作

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
import java.io.File;

// 创建文件
File file = new File("test.txt");
if (!file.exists()) {
file.createNewFile();
}

// 创建目录
File dir = new File("mydir");
dir.mkdir(); // 创建单级目录
dir.mkdirs(); // 创建多级目录

// 删除文件
file.delete();

// 文件信息
System.out.println("文件名: " + file.getName());
System.out.println("绝对路径: " + file.getAbsolutePath());
System.out.println("文件大小: " + file.length());
System.out.println("是否是目录: " + file.isDirectory());
System.out.println("是否是文件: " + file.isFile());

// 列出目录内容
File[] files = dir.listFiles();
for (File f : files) {
System.out.println(f.getName());
}

七、NIO

7.1 Channel和Buffer

1
2
3
4
5
6
7
8
9
10
11
12
13
// 使用NIO读取文件
try (FileChannel channel = FileChannel.open(
Paths.get("input.txt"), StandardOpenOption.READ)) {
ByteBuffer buffer = ByteBuffer.allocate(1024);

while (channel.read(buffer) != -1) {
buffer.flip(); // 切换到读模式
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
buffer.clear(); // 清空缓冲区
}
}

7.2 Files工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 读取所有行
List<String> lines = Files.readAllLines(Paths.get("input.txt"));

// 写入所有行
Files.write(Paths.get("output.txt"), lines);

// 复制文件
Files.copy(Paths.get("source.txt"), Paths.get("target.txt"));

// 删除文件
Files.delete(Paths.get("file.txt"));

// 遍历目录
Files.walk(Paths.get("mydir"))
.forEach(System.out::println);

八、实战示例

8.1 文件复制

1
2
3
4
5
6
7
8
9
10
11
12
13
public void copyFile(String source, String target) {
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(target)) {

byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}

8.2 文本文件统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void analyzeFile(String filename) throws IOException {
try (BufferedReader br = new BufferedReader(
new FileReader(filename))) {
int lines = 0;
int words = 0;
int chars = 0;

String line;
while ((line = br.readLine()) != null) {
lines++;
chars += line.length();
words += line.split("\\s+").length;
}

System.out.println("行数: " + lines);
System.out.println("单词数: " + words);
System.out.println("字符数: " + chars);
}
}

总结

Java IO核心:

  1. 字节流:处理二进制数据
  2. 字符流:处理文本数据
  3. 缓冲流:提高IO效率
  4. 对象流:序列化对象
  5. NIO:更高效的IO操作

参考资料