在 Java 中,I/O(输入/输出)操作主要通过 java.io 包中的字节流和字符流来实现,它们用于不同类型的数据处理。
一、字节流与字符流简介
1、字节流
字节流用于处理原始的二进制数据,适用于所有类型的文件(文本文件、图像、视频等)。
字节流部分类:
InputStream:所有字节输入流的超类。
FileInputStream:从文件中读取字节数据。
ByteArrayInputStream:从字节数组中读取字节数据。
BufferedInputStream:为其他输入流添加缓冲功能,提高读写效率。
DataInputStream:允许应用程序以机器无关方式读取基本 Java 数据类型。
OutputStream:所有字节输出流的超类。
FileOutputStream:将字节数据写入文件。
ByteArrayOutputStream:将字节数据写入字节数组。
BufferedOutputStream:为其他输出流添加缓冲功能,提高读写效率。
DataOutputStream:允许应用程序以机器无关方式写入基本 Java 数据类型。
2、字符流
字符流用于处理字符数据,专门设计用于处理文本文件。
字符流部分类:
Reader:所有字符输入流的超类。
FileReader:从文件中读取字符数据。
CharArrayReader:从字符数组中读取字符数据。
BufferedReader:为其他输入流添加缓冲功能,并提供 readLine 方法读取整行文本。
InputStreamReader:将字节输入流转换为字符输入流,常用于处理不同字符编码的文件。
StringReader:从字符串中读取字符数据。
Writer:所有字符输出流的超类。
FileWriter:将字符数据写入文件。
CharArrayWriter:将字符数据写入字符数组。
BufferedWriter:为其他输出流添加缓冲功能,并提供 newLine 方法写入换行符。
OutputStreamWriter:将字节输出流转换为字符输出流,常用于处理不同字符编码的文件。
StringWriter:将字符数据写入字符串缓冲区。
每个流对象都有特定的使用场景,想要正确输入输出还需要针对场景选择合适的流对象。
二、字节流与字符流简单应用
1、字节流应用示例
业务场景:复制一个图片。
public static void main(String[] args) {
// 源图片文件路径
String sourcePath = "source_image.png";
// 目标图片文件路径
String destPath = "dest_image.png";
// 创建输入和输出流
try (FileInputStream fis = new FileInputStream(sourcePath);
FileOutputStream fos = new FileOutputStream(destPath)) {
// 创建缓冲区
byte[] buffer = new byte[1024];
int bytesRead;
// 读取和写入数据
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
System.out.println("图片复制完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
注意事项:源文件必须存在,放在项目根目录下。
在示例代码中,第一步创建文件对象
直接使用文件路径字符串 "source_image.png" 和 "dest_image.png"。
第二步,打开文件字节流
使用FileInputStream和FileOutputStream分别创建文件字节输入流和输出流。
第三步,读写数据
创建一个字节数组缓冲区 buffer,大小为 1024 字节。
使用 while 循环读取输入流的数据,并将其写入输出流。
fis.read(buffer) 方法读取最多 buffer 大小的数据到缓冲区,并返回实际读取的字节数。如果读取完毕,返回 -1。
fos.write(buffer, 0, bytesRead) 方法将缓冲区中的数据写入输出流,从缓冲区的起始位置写入,长度为实际读取的字节数。
第四步,释放资源
使用 try-with-resources 语法,确保在 try 块结束时自动关闭输入输出流,避免资源泄漏。
2、字符流应用示例
业务场景:把一个txt中的内容拷贝到另一个txt中。
public static void main(String[] args) {
// 1、第一步,选择文件路径
String sourceFilePath = "source.txt"; // 源文件路径
String destFilePath = "destination.txt"; // 目标文件路径
// 2、第二步,打开文件流
try (BufferedReader reader = new BufferedReader(new FileReader(sourceFilePath));
BufferedWriter writer = new BufferedWriter(new FileWriter(destFilePath))) {
// 3、操作文件流
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine(); // 写入换行符
}
} catch (IOException e) {
e.printStackTrace();
}
}
在示例代码中,第一步创建文件对象
直接使用文件路径字符串 "source.txt" 和 "destination.txt"。
第二步,打开文件字符流
读取文件时,选择了带缓冲字符输入流BufferedReader和文件字符输入流FileReader,使用 new FileReader(sourceFilePath) 创建了源文件的读取流,将 FileReader 对象传递给 BufferedReader 构造函数。
写入文件时,选择了带缓冲字符输出流BufferedWriter和文件字符输出流FileWriter,使用 new FileWriter(destFilePath) 创建了目标文件的写入流, 将 FileWriter 对象传递给 BufferedWriter 构造函数。
第三步,操作文件字符流
使用 reader.readLine() 循环读取每一行内容。
使用 writer.write(line) 写入内容到目标文件。
使用 writer.newLine() 写入换行符,确保目标文件的格式正确。
第四步,关闭文件字符流
使用 Java 7 引入的 try-with-resources 语法,自动关闭文件流并处理异常。
四、最后总结
本文主要讲了两件事情,第一件字符流和字节流的区别,第二件如何使用流操作文件。
1、字节流和字符流的区别
字节流用于处理原始的二进制数据,类名通常以 InputStream 和 OutputStream 结尾。
符流用于处理字符数据,类名通常以 Reader 和 Writer 结尾。
如果是文本数据,建议使用字符流;如果是二进制数据(如图片、视频),建议使用字节流。
2、如何使用流操作文件?
四步就可以完成:
第一步,指定文件路径,创建一个文件对象。
第二步,选择合适的字节流或字符流,创建文件流对象打开文件流。
第三步,使用文件流对象操作文件内容。
第四步,关闭文件流,释放资源。
简单的文件读写、复制等都可以使用java io包中的字节流和字符流进行操作,还可以根据操作的数据类型选择使用哪种字节流或字符流。
领取专属 10元无门槛券
私享最新 技术干货