1. Java IO 类概述
1.1 什么是 IO
IO 是 Input/Output(输入/输出) 的缩写,代表了程序与外部环境(如文件、网络、设备等)之间进行数据交换的操作。在 Java 中,IO 操作广泛用于文件读取、写入、网络通信等场景。Java 提供了强大的 IO 类来简化这些操作,并按照不同的数据类型(如字节、字符)和数据源提供了不同的类。
1.2 Java 常用的 IO 类
根据数据处理的方式不同,Java 中的 IO 操作可以分为以下几大类:
- 字节流:处理二进制数据,适用于图片、音频、视频等非文本数据。
- 字符流:处理文本数据,适用于字符串、字符等文本文件。
Java IO 常用类如下表:
| 类别 | 输入类 | 输出类 |
|---|---|---|
| 字节流 | InputStream | OutputStream |
| 文件字节流 | FileInputStream | FileOutputStream |
| 字符流 | Reader | Writer |
| 文件字符流 | FileReader | FileWriter |
| 缓冲流 | BufferedInputStream | BufferedOutputStream |
| 缓冲字符流 | BufferedReader | BufferedWriter |
2. 字节流与字符流的区别
Java 中的 IO 操作分为两类:字节流 和 字符流。它们的区别在于处理的数据类型不同。
2.1 什么是字节流
字节流 以 8 位字节 为单位读取或写入数据,适合处理 二进制数据。字节流的常见用法是处理图片、视频、音频等非文本文件。字节流类的主要父类有:
InputStream:字节输入流,用于从数据源读取字节。OutputStream:字节输出流,用于将字节写入目标。
常用字节流类包括 FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream 等。
2.2 什么是字符流
字符流 以 16 位字符 为单位进行数据处理,适合处理 文本数据,如字符串和文本文件。字符流类的主要父类有:
Reader:字符输入流,用于读取字符数据。Writer:字符输出流,用于写入字符数据。
常用字符流类包括 FileReader、FileWriter、BufferedReader、BufferedWriter 等。
2.3 字节流与字符流的区别
| 区别点 | 字节流 | 字符流 |
|---|---|---|
| 处理的数据类型 | 处理二进制数据,如图片、音频 | 处理文本数据,如文本文件、字符串 |
| 数据单位 | 以字节为单位(8 位) | 以字符为单位(16 位) |
| 使用场景 | 适用于非文本文件的处理 | 适用于文本文件或字符数据的处理 |
| 父类 | InputStream 和 OutputStream | Reader 和 Writer |
| 常用类 | FileInputStream,FileOutputStream | FileReader,FileWriter |
3. Java IO 常用字节流类
字节流主要用于处理非文本数据。Java 提供了丰富的字节流类来帮助开发者进行文件或网络数据的操作。
3.1 InputStream 类
InputStream 是字节输入流的父类,定义了从不同的输入源(如文件、网络、内存缓冲区)读取字节的基本方法。
常用的 InputStream 子类包括:
FileInputStream:用于从文件中读取字节数据。BufferedInputStream:为其他输入流提供缓冲功能,提高读取效率。ByteArrayInputStream:从字节数组中读取数据。
3.2 OutputStream 类
OutputStream 是字节输出流的父类,定义了向不同的输出目标(如文件、网络、内存缓冲区)写入字节的基本方法。
常用的 OutputStream 子类包括:
FileOutputStream:用于将字节数据写入文件。BufferedOutputStream:为其他输出流提供缓冲功能,提高写入效率。ByteArrayOutputStream:向字节数组中写入数据。
3.3 FileInputStream 和 FileOutputStream 示例
示例:读取二进制文件
通过 FileInputStream 读取二进制文件(如图片),并将其保存到字节数组中:
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputExample {
public static void main(String[] args) {
String filePath = "image.jpg"; // 文件路径
try (FileInputStream fis = new FileInputStream(filePath)) {
byte[] data = new byte[fis.available()];
fis.read(data); // 将文件内容读取到字节数组中
System.out.println("读取了 " + data.length + " 个字节的数据");
} catch (IOException e) {
e.printStackTrace();
}
}
}
示例:写入二进制文件
通过 FileOutputStream 将字节数据写入文件:
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputExample {
public static void main(String[] args) {
String filePath = "output.jpg"; // 输出文件路径
byte[] data = { /* 图片的字节数据 */ };
try (FileOutputStream fos = new FileOutputStream(filePath)) {
fos.write(data); // 将字节数据写入文件
System.out.println("写入了 " + data.length + " 个字节的数据");
} catch (IOException e) {
e.printStackTrace();
}
}
}
在这两个例子中,使用了 try-with-resources 语法来确保流的正确关闭,防止资源泄漏。
4. Java IO 常用字符流类
字符流用于处理文本数据,如字符串或文本文件的读取和写入。字符流以 Reader 和 Writer 为父类,分别对应输入和输出操作。
4.1 Reader 类
Reader 是字符输入流的父类,用于从各种输入源(如文件、内存缓冲区、网络连接)读取字符数据。
常用的 Reader 子类包括:
FileReader:从文件中读取字符数据。BufferedReader:提供缓冲功能以提高读取效率。
4.2 Writer 类
Writer 是字符输出流的父类,用于将字符数据写入输出目标(如文件、内存缓冲区、网络连接)。
常用的 Writer 子类包括:
FileWriter:向文件写入字符数据。BufferedWriter:提供缓冲功能以提高写入效率。
4.3 FileReader 和 FileWriter 示例
示例:读取文本文件
通过 FileReader 和 BufferedReader 读取文本文件的内容:
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
public class FileReaderExample {
public static void main(String[] args) {
String filePath = "example.txt"; // 文件路径
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line); // 输出文件的每一行
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
示例:写入文本文件
通过 FileWriter 和 BufferedWriter 将文本数据写入文件:
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;
public class FileWriterExample {
public static void main(String[] args) {
String filePath = "output.txt"; // 输出文件路径
String content = "这是写入文件的文本内容。";
try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath))) {
bw.write(content); // 写入文本内容
bw.newLine(); // 换行
bw.write("这是另一行文本。");
System.out.println("文本内容已成功写入文件。");
} catch (IOException e) {
e.printStackTrace();
}
}
}
5. Java 读取和写入文本的综合示例
结合读取和写入操作,展示如何读取一个文件的内容,并将其写入到另一个文件中。
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;
public class FileCopyExample {
public static void main(String[] args) {
String inputFilePath = "input.txt"; // 输入文件路径
String outputFilePath = "output.txt"; // 输出文件路径
try (
BufferedReader br = new BufferedReader(new FileReader(inputFilePath));
BufferedWriter bw = new BufferedWriter(new FileWriter(outputFilePath))
) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line); // 将读取的行写入输出文件
bw.newLine(); // 写入换行符
}
System.out.println("文件内容已成功复制到新的文件。");
} catch (IOException e) {
e.printStackTrace();
}
}
}
此示例通过 BufferedReader 读取文本文件,并通过 BufferedWriter 将内容写入到另一个文件中,确保了高效读取和写入操作。
6. 流泄漏问题及如何正确关闭流
6.1 流泄漏问题
在进行 IO 操作时,未能正确关闭流对象会导致资源泄漏问题。Java 的 IO 操作通常涉及文件句柄、网络连接等有限资源,如果这些资源未能及时释放,可能会引发以下问题:
- 文件锁未释放:如果文件流未关闭,文件可能仍被锁定,导致其他程序无法访问该文件。
- 资源消耗过高:长时间不释放 IO 资源会导致系统资源(如文件句柄)耗尽,从而引发性能问题或系统崩溃。
6.2 如何正确关闭流
为了解决流泄漏问题,Java 提供了多种方法来确保流在使用后被正确关闭:
方法1:显式关闭流
使用 try-finally 结构手动关闭流。
import java.io.FileInputStream;
import java.io.IOException;
public class ExplicitCloseExample {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("example.txt");
// 执行读取操作
} catch (IOException e) {
e.printStackTrace();
} finally {
// 确保在 finally 中关闭流
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
方法2:使用 try-with-resources
从 Java 7 开始,提供了 try-with-resources 语法,该结构可以自动关闭实现了 AutoCloseable 接口的资源类,避免了手动关闭流的麻烦。
import java.io.FileInputStream;
import java.io.IOException;
public class TryWithResourcesExample {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("example.txt")) {
// 执行读取操作
} catch (IOException e) {
e.printStackTrace();
}
// 文件流会自动关闭
}
}
try-with-resources 是推荐的方式,它能够确保即使发生异常,也会自动关闭流,极大地减少了流泄漏的可能性。


















