Java的输入输出(I/O)流提供了读取和写入数据的标准方法。Java的I/O流基于四个抽象类:InputStream
、OutputStream
(用于字节流)和Reader
、Writer
(用于字符流)。通过这些抽象类的多种实现,Java能够处理文件、网络数据等各种输入输出操作。
字节流和字符流
- 字节流(Byte Streams):处理原始二进制数据,最常见的类有
FileInputStream
和FileOutputStream
。 - 字符流(Character Streams):处理字符数据,自动处理字符编码问题,最常见的类有
FileReader
和FileWriter
。
基本的文件读写
使用字节流读写文件
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyBytes {
public static void main(String[] args) throws IOException {
try (FileInputStream in = new FileInputStream("xanadu.txt");
FileOutputStream out = new FileOutputStream("outagain.txt")) {
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}
}
}
在上面的示例中,FileInputStream
和FileOutputStream
是用于读取和写入文件的字节流。整个文件的内容一个字节一个字节地被读取并写入到另一个文件中。
使用字符流读写文件
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyCharacters {
public static void main(String[] args) throws IOException {
try (FileReader inputStream = new FileReader("xanadu.txt");
FileWriter outputStream = new FileWriter("characteroutput.txt")) {
int c;
while ((c = inputStream.read()) != -1) {
outputStream.write(c);
}
}
}
}
FileReader
和FileWriter
是用于读取和写入文件的字符流。和字节流示例类似,但这里处理的是字符数据。
缓冲流
缓冲流(Buffered Streams)提供了缓冲的读写,以减少实际的I/O操作次数,从而提高性能。对于文件处理,最常用的缓冲流是BufferedReader
和BufferedWriter
。
使用缓冲字符流读写文件
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyLines {
public static void main(String[] args) throws IOException {
try (BufferedReader inputStream = new BufferedReader(new FileReader("xanadu.txt"));
BufferedWriter outputStream = new BufferedWriter(new FileWriter("lineoutput.txt"))) {
String l;
while ((l = inputStream.readLine()) != null) {
outputStream.write(l);
outputStream.newLine(); // 添加换行符
}
}
}
}
在上面的示例中,BufferedReader
和BufferedWriter
被使用来高效地读取和写入文件,每次操作一行数据。
对象序列化
Java提供了对象序列化机制,允许将对象转换为字节序列,从而可以将对象持久化到文件中,或通过网络发送给其他程序。
序列化和反序列化示例
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Student implements Serializable {
private static final long serialVersionUID = 1L;
String name;
int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
}
public class SerializeDemo {
public static void main(String[] args) {
// 序列化
Student s = new Student("John", 20);
try (FileOutputStream fos = new FileOutputStream("student.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(s);
} catch (IOException e) {
e.printStackTrace();
}
// 反序列化
try (FileInputStream fis = new FileInputStream("student.ser");
ObjectInputStream ois = new ObjectInputStream(fis)) {
Student s1 = (Student) ois.readObject();
System.out.println(s1.name + " " + s1.age);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
这里我们创建了一个Student
类的实例,将其序列化并写入到student.ser
文件。随后,我们通过反序列化读取这个文件,并恢复成Student
对象。
注意Student
类实现了Serializable
接口,这是一个标记接口,它告诉Java该类的对象可以被序列化。我们还提供了一个serialVersionUID
字段,它是序列化对象的版本标识符。这个字段是可选的,但强烈建议添加,以提供版本兼容性。
Java NIO
Java NIO(New I/O)是Java 1.4及以后版本提供的一个替代传统I/O API的选项。它提供了缓冲区操作数据、非阻塞I/O和选择器监控多个带有数据通道的输入输出等高级特性。
使用Path和Files类简化文件操作
Java NIO中的java.nio.file
包提供了Path
和Files
等工具类,可以用来更加方便地处理文件和目录路径。
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class NIODemo {
public static void main(String[] args) {
Path sourcePath = Paths.get("xanadu.txt");
Path destinationPath = Paths.get("outagain_nio.txt");
try {
// 复制文件
Files.copy(sourcePath, destinationPath);
// 读取文件
List<String> lines = Files.readAllLines(sourcePath);
// 写入文件
Files.write(destinationPath, lines);
} catch (IOException e) {
e.printStackTrace();
}
}
}
这个例子演示了如何使用NIO的Files
类来读取、写入和复制文件。方法调用更加简洁直观,而且文件操作更加强大。
结论
Java提供了丰富的I/O流类来处理各种数据输入输出需求,包括字节流、字符流、缓冲流、对象流等,以及用于文件操作的NIO类。通过这些工具,你可以高效地读取和写入数据,无论是文件、网络还是其他数据源。掌握Java I/O和NIO是成为一名熟练Java开发者的重要步骤。