在 Java 开发中,IO 流是处理输入输出操作的重要工具,广泛应用于文件读写、网络通信等场景。本文将带你深入学习 Java IO 流的核心概念、常用类与方法,以及实际应用技巧。
一、IO 流概述
-
什么是 IO 流? IO 是 Input/Output 的缩写,意为输入 / 输出。在 Java 中,流是一种用于传输数据的抽象概念,数据以流的形式从数据源(如文件、网络)流向目的地(如内存、文件)。
-
流的分类
-
按数据单位划分 :
-
字节流(Byte Stream) :以字节(8 位)为单位进行数据传输,适用于处理二进制数据,如图片、音频、视频等文件。常见的字节流类有
InputStream
(输入流)、OutputStream
(输出流)及其子类。 -
字符流(Character Stream) :以字符(16 位)为单位进行数据传输,适用于处理文本数据。字符流类包括
Reader
(输入流)、Writer
(输出流)及其子类。字符流在处理文本时会考虑字符编码,更方便地处理 Unicode 字符。
-
-
按流向划分 :
-
输入流 :从数据源读取数据到程序中,如
InputStream
、Reader
。 -
输出流 :将程序中的数据写入到目的地,如
OutputStream
、Writer
。
-
-
二、字节流的使用
-
FileInputStream(文件输入流)
-
功能 :用于从文件中读取数据。
-
常用方法 :
-
int read()
:读取一个字节的数据,返回读取的字节值(0~255),若到达文件末尾返回 -1。 -
int read(byte[] b)
:将数据读取到字节数组b
中,返回实际读取的字节数,若到达文件末尾返回 -1。
-
-
示例代码 :读取文件内容并输出到控制台
-
FileInputStream fis = null;
try {
fis = new FileInputStream("input.txt");
byte[] buffer = new byte[1024]; // 创建缓冲区
int len;
while ((len = fis.read(buffer)) != -1) {
System.out.write(buffer, 0, len); // 输出到控制台
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close(); // 关闭流,释放资源
} catch (IOException e) {
e.printStackTrace();
}
}
}
-
FileOutputStream(文件输出流)
-
功能 :将数据写入到文件中。
-
常用方法 :
-
void write(int b)
:写入一个字节的数据。 -
void write(byte[] b)
:将字节数组b
中的数据写入文件。
-
-
示例代码 :将字符串写入文件
-
FileOutputStream fos = null;
try {
fos = new FileOutputStream("output.txt");
String content = "Hello, IO!";
fos.write(content.getBytes()); // 将字符串转换为字节数组并写入文件
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
三、字符流的使用
-
FileReader(文件字符输入流)
-
功能 :用于从文件中读取字符数据。
-
常用方法 :
-
int read()
:读取一个字符,返回读取的字符(0~65535),若到达文件末尾返回 -1。 -
int read(char[] cbuf)
:将数据读取到字符数组cbuf
中,返回实际读取的字符数,若到达文件末尾返回 -1。
-
-
示例代码 :读取文本文件内容并输出
-
FileReader fr = null;
try {
fr = new FileReader("input.txt");
char[] buffer = new char[1024];
int len;
while ((len = fr.read(buffer)) != -1) {
System.out.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
-
FileWriter(文件字符输出流)
-
功能 :将字符数据写入到文件中。
-
常用方法 :
-
void write(int c)
:写入一个字符。 -
void write(char[] cbuf)
:将字符数组cbuf
中的数据写入文件。 -
void write(String str)
:写入字符串。
-
-
示例代码 :向文件写入文本内容
-
FileWriter fw = null;
try {
fw = new FileWriter("output.txt");
fw.write("Hello, Java IO!");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
四、缓冲流(BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter)
缓冲流是对基本流的封装,通过引入缓冲区,减少实际的 IO 操作次数,提高数据读写效率。
-
BufferedInputStream / BufferedOutputStream(字节缓冲流)
-
使用方法 :在创建字节流对象后,将其作为参数传递给缓冲流构造方法,如
BufferedInputStream(InputStream in)
。 -
示例代码 :使用缓冲流复制文件
-
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream("source.jpg"));
bos = new BufferedOutputStream(new FileOutputStream("dest.jpg"));
byte[] buffer = new byte[4096]; // 4KB 缓冲区
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.flush(); // 刷新输出流,确保数据写入文件
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭缓冲流即可,会自动关闭底层的基本流
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
-
BufferedReader / BufferedWriter(字符缓冲流)
-
常用方法 :
-
BufferedReader
:String readLine()
读取一行数据,返回包含换行符之前内容的字符串,若到达文件末尾返回 null。 -
BufferedWriter
:void newLine()
写入一个行分隔符,跨平台兼容。
-
-
示例代码 :读取文本文件并逐行输出
-
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("input.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
五、注意事项
-
正确关闭流 在使用完 IO 流后,务必及时关闭流,释放系统资源。通常在
finally
块中进行关闭操作。对于缓冲流,关闭缓冲流会自动关闭底层的基本流。 -
异常处理 IO 操作可能会抛出
IOException
,需要使用try-catch
块进行异常捕获和处理,避免程序因异常中断。 -
字符编码问题 在使用字符流处理文本文件时,要注意字符编码的一致性,避免出现乱码。常见的字符编码有 UTF-8、GBK 等。
通过学习 Java IO 流,我们可以高效地处理文件读写、数据传输等操作,为 Java 应用开发提供强大的数据处理能力。在实际项目中,结合不同场景选择合适的流类型和操作方式,能够更好地满足业务需求。