1. IO简介
在Java中,IO(Input/Output)流是用来处理输入和输出数据的机制。通过IO流,Java可以与文件、网络、控制台等设备进行数据交互。
1.1 什么是IO
IO流是用于处理数据传输的工具,它通过输入流(Input Stream)来读取数据,通过输出流(Output Stream)来写入数据。数据的传输可以来自文件、内存、网络等。
我们把这种数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为输入input
和输出output
,即流向内存是输入流,流出内存的输出流。
Java中I/O操作主要是指使用java.io
包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据。
1.2 IO的分类
Java中的IO流主要分为以下两类:
-
按处理数据的单位分类:
- 字节流(Byte Stream):以字节为单位进行数据读写。
- 字符流(Character Stream):以字符为单位进行数据读写。
-
按数据流的方向分类:
- 输入流(Input Stream/Reader):数据从
其他设备
上读取到内存
中的流。 - 输出流(Output Stream/Writer):把数据从
内存
中写出到其他设备
上的流。
- 输入流(Input Stream/Reader):数据从
2. 字节流
2.1 字节流概念
字节流以字节(8-bit)为单位进行数据处理。它适用于所有类型的数据,包括图片、音频、视频等,因为字节流能处理所有类型的二进制数据。
一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。
2.2 字节流的主要类
-
InputStream:字节输入流的基类,用于从数据源读取字节数据。常见的子类有:
FileInputStream
:从文件中读取字节数据。ByteArrayInputStream
:从字节数组中读取数据。
-
OutputStream:字节输出流的基类,用于向目标写入字节数据。常见的子类有:
FileOutputStream
:向文件中写入字节数据。ByteArrayOutputStream
:将字节写入内存中的字节数组。
代码示例:图片拷贝
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Copy {
public static void main(String[] args) throws IOException {
// 1. 创建流对象
// 1.1 创建文件输入流对象,指定数据源(待复制的文件路径)
// 这里将会从 "D:\\test.jpg" 文件中读取数据
FileInputStream fis = new FileInputStream("D:\\test.jpg");
// 1.2 创建文件输出流对象,指定目的地(目标复制文件路径)
// 这里会将数据写入到当前目录下的 "test_copy.jpg" 文件中
FileOutputStream fos = new FileOutputStream("test_copy.jpg");
// 2. 读写数据
// 2.1 定义一个字节数组作为缓冲区,用来存放每次从输入流中读取的数据
// 数组大小设为 1024 字节(即1KB),可以根据实际需求调整大小
byte[] b = new byte[1024];
// 2.2 定义一个整数变量 len,用于记录每次读取的字节数
int len;
// 2.3 循环读取数据
// 调用输入流的 read() 方法,每次读取最多 1024 字节的数据到字节数组 b 中
// 当 read() 方法返回 -1 时,表示数据已经读完
while ((len = fis.read(b)) != -1) {
// 2.4 写出数据
// 调用输出流的 write() 方法,将读取到的字节数据从缓冲区写入到目标文件
// len 表示实际读取的字节数,避免写入多余的数据
fos.write(b, 0, len);
}
// 3. 关闭资源
// 3.1 关闭输出流,确保数据完全写入目标文件
fos.close();
// 3.2 关闭输入流,释放系统资源
fis.close();
}
}
3. 字符流
3.1 字符流概念
当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。
字符流以字符(16-bit Unicode)为单位进行数据处理。它适用于处理文本数据,如处理普通文本文件(txt
),能够自动识别字符编码,避免编码不匹配的问题。
3.2 字符流的主要类
-
Reader:字符输入流的基类,用于从数据源读取字符。常见的子类有:
FileReader
:从文件中读取字符数据。BufferedReader
:通过缓冲方式高效地读取字符数据。
-
Writer:字符输出流的基类,用于向目标写入字符。常见的子类有:
FileWriter
:向文件中写入字符数据。BufferedWriter
:通过缓冲方式高效地写入字符数据。
代码示例:文本拷贝
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CharStreamCopy {
public static void main(String[] args) throws IOException {
// 1. 创建字符输入流和字符输出流
// 1.1 创建字符输入流对象,指定数据源文件 (例如 "input.txt")
FileReader fr = new FileReader("input.txt");
// 1.2 创建字符输出流对象,指定目标文件 (例如 "output.txt")
FileWriter fw = new FileWriter("output.txt");
// 2. 读取和写入数据
// 2.1 定义一个字符数组作为缓冲区,用于存储每次读取的字符数据
char[] buffer = new char[1024]; // 每次读取最多 1024 个字符
// 2.2 定义一个整数变量 len,用来记录每次实际读取的字符数
int len;
// 2.3 使用循环来读取数据,直到读取完毕
while ((len = fr.read(buffer)) != -1) {
// 2.4 将缓冲区中读取到的字符写入到目标文件
fw.write(buffer, 0, len);
}
// 3. 关闭资源
// 3.1 关闭输出流,确保数据完全写入文件
fw.close();
// 3.2 关闭输入流,释放资源
fr.close();
}
}