Java IO 流概述
Java 的 I/O 流是 Java 中处理数据输入输出的基础机制。I/O 流提供了访问外部数据(如文件、网络、键盘等)和将数据写入外部的标准方式。
Java IO 包主要包含 java.io
包下的多种类,主要分为 字节流 和 字符流,分别用于处理不同类型的数据。
1. Java IO 流的分类
1.1 字节流
字节流是按字节处理数据的流,用于处理所有类型的 I/O 操作,尤其是二进制数据(如图片、音频文件等)。字节流类主要包括:
- InputStream(输入流):
FileInputStream
,BufferedInputStream
,ObjectInputStream
- OutputStream(输出流):
FileOutputStream
,BufferedOutputStream
,ObjectOutputStream
1.2 字符流
字符流是按字符处理数据的流,主要用于处理文本数据。字符流使用 Unicode 编码,能够处理国际化字符。字符流类主要包括:
- Reader(读取流):
FileReader
,BufferedReader
,InputStreamReader
- Writer(写入流):
FileWriter
,BufferedWriter
,OutputStreamWriter
2. 字节流的使用
字节流适用于所有类型的文件,包括图片、音频、视频等。字节流提供了基本的输入输出功能。常用的字节流类包括 FileInputStream
, FileOutputStream
,以及它们的缓冲流版本 BufferedInputStream
, BufferedOutputStream
。
2.1 示例:使用 FileInputStream 和 FileOutputStream
import java.io.*;
public class ByteStreamExample {
public static void main(String[] args) {
try {
// 创建文件输入流读取文件
FileInputStream fis = new FileInputStream("source.txt");
// 创建文件输出流写入文件
FileOutputStream fos = new FileOutputStream("destination.txt");
int byteData;
// 读取文件并写入到新文件
while ((byteData = fis.read()) != -1) {
fos.write(byteData);
}
fis.close();
fos.close();
System.out.println("File copy completed using byte streams.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
在这个示例中,我们使用 FileInputStream
和 FileOutputStream
对文件进行字节级别的读写操作。每次读取一个字节,将其写入到目标文件中。
2.2 示例:使用 BufferedInputStream 和 BufferedOutputStream
import java.io.*;
public class BufferedByteStreamExample {
public static void main(String[] args) {
try {
// 创建缓冲输入流和输出流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("source.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("destination.txt"));
int byteData;
// 通过缓冲流读取和写入
while ((byteData = bis.read()) != -1) {
bos.write(byteData);
}
bis.close();
bos.close();
System.out.println("File copy completed using buffered byte streams.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
在这个例子中,使用了 BufferedInputStream
和 BufferedOutputStream
,它们通过缓存来优化 I/O 操作,减少了直接读写磁盘的次数,从而提升了性能。
3. 字符流的使用
字符流主要用于文本文件的读写。由于字符流是基于字符处理的,它会自动处理字符编码(如 UTF-8 或 UTF-16),所以字符流更加适合处理文本数据。
3.1 示例:使用 FileReader 和 FileWriter
import java.io.*;
public class CharStreamExample {
public static void main(String[] args) {
try {
// 创建字符输入流读取文件
FileReader fr = new FileReader("source.txt");
// 创建字符输出流写入文件
FileWriter fw = new FileWriter("destination.txt");
int charData;
// 读取字符并写入
while ((charData = fr.read()) != -1) {
fw.write(charData);
}
fr.close();
fw.close();
System.out.println("File copy completed using character streams.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
在这个示例中,我们使用 FileReader
和 FileWriter
来进行字符级别的读写操作。与字节流相比,字符流更适合处理文本数据,尤其是包含国际化字符的文本。
3.2 示例:使用 BufferedReader 和 BufferedWriter
import java.io.*;
public class BufferedCharStreamExample {
public static void main(String[] args) {
try {
// 创建缓冲字符输入流和输出流
BufferedReader br = new BufferedReader(new FileReader("source.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("destination.txt"));
String line;
// 使用缓冲流逐行读取并写入
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine(); // 写入换行符
}
br.close();
bw.close();
System.out.println("File copy completed using buffered character streams.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
在这个例子中,我们使用 BufferedReader
和 BufferedWriter
来读取和写入文件。BufferedReader
的 readLine()
方法允许按行读取文本文件,适用于文本数据处理。
4. 数据流(DataStream)
数据流是字节流的一种,主要用于读取和写入 Java 原生数据类型(如 int
, float
, double
, boolean
等)。通过 DataInputStream
和 DataOutputStream
,可以方便地进行跨平台的二进制数据交换。
4.1 示例:使用 DataInputStream 和 DataOutputStream
import java.io.*;
public class DataStreamExample {
public static void main(String[] args) {
try {
// 创建数据输出流
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.dat"));
// 写入基本数据类型
dos.writeInt(123);
dos.writeDouble(45.67);
dos.writeBoolean(true);
dos.close();
// 创建数据输入流
DataInputStream dis = new DataInputStream(new FileInputStream("data.dat"));
// 读取基本数据类型
int num = dis.readInt();
double d = dis.readDouble();
boolean bool = dis.readBoolean();
dis.close();
System.out.println("Read data: " + num + ", " + d + ", " + bool);
} catch (IOException e) {
e.printStackTrace();
}
}
}
在这个例子中,我们通过 DataOutputStream
写入基本数据类型,通过 DataInputStream
读取相应的类型。使用数据流可以方便地写入和读取原始数据。
5. 对象流(ObjectStream)
对象流主要用于对象的序列化与反序列化,允许我们将 Java 对象转化为字节流以进行存储或传输。通过 ObjectOutputStream
和 ObjectInputStream
,可以将对象序列化后写入文件,并从文件中读取恢复成对象。
5.1 示例:使用 ObjectOutputStream 和 ObjectInputStream
import java.io.*;
class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public class ObjectStreamExample {
public static void main(String[] args) {
try {
// 创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"));
// 创建 Person 对象并序列化
Person person = new Person("Alice", 30);
oos.writeObject(person);
oos.close();
// 创建对象输入流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"));
// 反序列化对象
Person deserializedPerson = (Person) ois.readObject();
ois.close();
System.out.println("Deserialized Person: " + deserializedPerson.getName() + ", " + deserializedPerson.getAge());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
在这个例子中,我们使用 ObjectOutputStream
将 Person
对象序列化到文件,然后使用 ObjectInputStream
从文件中反序列化该对象。需要注意的是,被序列化的类必须实现 Serializable
接口。
6. 总结
- 字节流:用于处理所有类型的 I/O
,尤其是二进制数据。
- 例如,
FileInputStream
,FileOutputStream
,BufferedInputStream
,BufferedOutputStream
- 字符流:专门用于处理文本数据,能够自动处理字符编码。
- 例如,
FileReader
,FileWriter
,BufferedReader
,BufferedWriter
- 例如,
- 数据流:专门用于处理原始数据类型的读写。
- 例如,
DataInputStream
,DataOutputStream
- 例如,
- 对象流:用于对象的序列化和反序列化。
- 例如,
ObjectInputStream
,ObjectOutputStream
- 例如,
I/O 流是 Java 中非常重要的概念,广泛用于文件处理、网络通信等场景。理解和掌握这些流的使用方法,可以帮助开发者高效地处理数据。
来一杯咖啡,聊聊Java的碎碎念呀