在Java中,IO(输入/输出)流是处理数据传输的核心机制。Java通过输入流和输出流来操作数据,支持多种数据类型和操作场景。Java IO流可以分为字节流和字符流两大类,每类又细分为节点流和处理流。本文将详细介绍Java IO流的分类及其应用场景,并通过代码示例帮助理解。
一、字节流与字符流
(一)字节流(Byte Stream)
字节流是最基本的IO流,用于处理二进制数据。它通过操作字节(byte)来传输数据,适合所有类型的数据,包括文本、图片、音频等。字节流的核心类是 InputStream (输入流)和 OutputStream (输出流)。
字节流的典型应用场景:
- 文件的读写操作。
- 读取或写入二进制数据,如图片或音频文件。
示例:字节流复制文件
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteStreamExample {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt")) {
int byteData;
while ((byteData = fis.read()) != -1) {
fos.write(byteData); // 按字节写入数据
}
System.out.println("File copied successfully using byte streams!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
解析 : FileInputStream 和 FileOutputStream 是字节流的实例,用于从文件中读取和向文件中写入数据。 read() 和 write() 方法是字节流操作的基本方法,分别用于读取字节数据和写入字节数据。
(二)字符流(Character Stream)
字符流用于处理字符数据,能够根据平台的字符编码(如UTF-8或GBK)自动将字节数据转换为字符。字符流是基于Unicode编码的,因此在处理文本文件时非常方便。字符流的核心类是 Reader (输入流)和 Writer (输出流)。
字符流的典型应用场景:
- 文本文件的读写操作。
- 处理基于字符的编码数据。
示例:字符流复制文件
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CharacterStreamExample {
public static void main(String[] args) {
try (FileReader fr = new FileReader("input.txt");
FileWriter fw = new FileWriter("output.txt")) {
int charData;
while ((charData = fr.read()) != -1) {
fw.write(charData); // 按字符写入数据
}
System.out.println("File copied successfully using character streams!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
解析 : FileReader 和 FileWriter 是字符流的实例,用于从文件中读取和向文件中写入字符数据。字符流比字节流更加简便和高效,特别是在处理文本文件时。
二、节点流与处理流
(一)节点流(Node Stream)
节点流是直接与数据源(如文件、网络等)进行交互的流。它们能够直接读取或写入数据。
- 字节流的节点流 :如 FileInputStream 和 FileOutputStream 。
- 字符流的节点流 :如 FileReader 和 FileWriter 。
(二)处理流(Processing Stream)
处理流是对节点流的包装,用于增强节点流的功能,如缓冲、数据转换、对象序列化等。处理流通常不直接与数据源交互,而是处理数据流中的内容。
- 字节流的处理流:
如 BufferedInputStream 、 BufferedOutputStream 、 DataInputStream 、 DataOutputStream
- 字符流的处理流 :如 BufferedReader 、 BufferedWriter 、 PrintWriter 。
示例:使用缓冲流读取文件
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderExample {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("input.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line); // 按行读取数据
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
解析 : BufferedReader 是字符流的处理流,用于高效读取文本文件。它使用缓冲区来减少磁盘访问次数,提高读取效率。 readLine() 方法逐行读取文件内容。
三、Java IO流的常见应用
(一)文件操作
文件操作是Java IO流最常见的用途之一。通过字节流和字符流,我们可以实现文件的读写、复制、删除等功能。文件操作中最常用的流包括 FileInputStream 、 FileOutputStream 、 FileReader 、 FileWriter 等。
(二)数据流
Java中的数据流用于处理基本数据类型(如 int 、 float 、 double 等)以及字符串。数据流可以自动处理数据的序列化与反序列化。
示例:使用数据流处理文件
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataStreamExample {
public static void main(String[] args) {
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"))) {
// 写入数据
dos.writeInt(100);
dos.writeDouble(3.14);
// 读取数据
System.out.println("Int value: " + dis.readInt());
System.out.println("Double value: " + dis.readDouble());
} catch (IOException e) {
e.printStackTrace();
}
}
}
解析 : DataInputStream 和 DataOutputStream 用于以平台无关的方式读写基本数据类型,如整数、浮点数等。
(三)序列化流与反序列化流
1. 对象序列化
对象序列化是将对象转换为字节流的过程,目的是将对象的状态保存到文件或通过网络传输。Java提供了 ObjectOutputStream 来实现对象的序列化。
示例:对象序列化
import java.io.*;
class Person implements Serializable {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class SerializationExample {
public static void main(String[] args) {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
Person person = new Person("John", 30);
oos.writeObject(person); // 序列化对象
} catch (IOException e) {
e.printStackTrace();
}
}
}
2. 对象反序列化
对象反序列化是将字节流重新转换为对象的过程,用于恢复对象的状态。Java提供了 ObjectInputStream 来实现对象的反序列化。
示例:对象反序列化
import java.io.*;
public class DeserializationExample {
public static void main(String[] args) {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
Person person = (Person) ois.readObject(); // 反序列化对象
System.out.println("Name: " + person.name + ", Age: " + person.age);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
解析 :序列化将对象转换为字节流,便于存储或传输;反序列化将字节流重新转换为对象,恢复对象的状态。