IO流、文件操作、序列化完整案例项目
项目结构
src/
├── main/
│ ├── java/
│ │ ├── file/
│ │ │ ├── FileManager.java
│ │ │ └── FileOperationsDemo.java
│ │ ├── io/
│ │ │ ├── ByteStreamDemo.java
│ │ │ ├── CharacterStreamDemo.java
│ │ │ └── BufferedStreamDemo.java
│ │ ├── serialization/
│ │ │ ├── Employee.java
│ │ │ ├── SerializationDemo.java
│ │ │ └── CustomSerializationDemo.java
│ │ └── MainApplication.java
│ └── resources/
│ ├── input.txt
│ ├── output.txt
│ └── data/
└── test/
└── java/
核心类实现
1. 序列化实体类 - Employee.java
package serialization;
import java.io.Serializable;
import java.time.LocalDate;
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private String department;
private Double salary;
private transient LocalDate hireDate; // 不参与序列化
public Employee() {}
public Employee(Long id, String name, String department, Double salary, LocalDate hireDate) {
this.id = id;
this.name = name;
this.department = department;
this.salary = salary;
this.hireDate = hireDate;
}
// Getters and Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getDepartment() { return department; }
public void setDepartment(String department) { this.department = department; }
public Double getSalary() { return salary; }
public void setSalary(Double salary) { this.salary = salary; }
public LocalDate getHireDate() { return hireDate; }
public void setHireDate(LocalDate hireDate) { this.hireDate = hireDate; }
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + '\'' +
", department='" + department + '\'' +
", salary=" + salary +
", hireDate=" + hireDate +
'}';
}
}
2. 字节流操作 - ByteStreamDemo.java
package io;
import java.io.*;
public class ByteStreamDemo {
/**
* 使用FileInputStream和FileOutputStream进行文件复制
*/
public static void copyFileWithByteStream(String sourceFile, String targetFile) {
try (FileInputStream fis = new FileInputStream(sourceFile);
FileOutputStream fos = new FileOutputStream(targetFile)) {
int byteData;
while ((byteData = fis.read()) != -1) {
fos.write(byteData);
}
System.out.println("字节流文件复制完成");
} catch (IOException e) {
System.err.println("字节流操作异常: " + e.getMessage());
}
}
/**
* 使用缓冲字节流提高效率
*/
public static void copyFileWithBufferedByteStream(String sourceFile, String targetFile) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFile))) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
System.out.println("缓冲字节流文件复制完成");
} catch (IOException e) {
System.err.println("缓冲字节流操作异常: " + e.getMessage());
}
}
/**
* 读取二进制文件并显示十六进制内容
*/
public static void readBinaryFileAsHex(String fileName) {
try (FileInputStream fis = new FileInputStream(fileName)) {
int byteData;
int count = 0;
System.out.println("文件十六进制内容:");
while ((byteData = fis.read()) != -1) {
System.out.printf("%02X ", byteData);
count++;
if (count % 16 == 0) {
System.out.println();
}
}
System.out.println();
} catch (IOException e) {
System.err.println("读取二进制文件异常: " + e.getMessage());
}
}
}
3. 字符流操作 - CharacterStreamDemo.java
package io;
import java.io.*;
import java.nio.charset.StandardCharsets;
public class CharacterStreamDemo {
/**
* 使用FileReader和FileWriter进行文本文件读写
*/
public static void writeTextFile(String fileName, String content) {
try (FileWriter writer = new FileWriter(fileName, StandardCharsets.UTF_8)) {
writer.write(content);
System.out.println("文本文件写入完成");
} catch (IOException e) {
System.err.println("写入文本文件异常: " + e.getMessage());
}
}
/**
* 读取文本文件内容
*/
public static String readTextFile(String fileName) {
StringBuilder content = new StringBuilder();
try (FileReader reader = new FileReader(fileName, StandardCharsets.UTF_8);
BufferedReader bufferedReader = new BufferedReader(reader)) {
String line;
while ((line = bufferedReader.readLine()) != null) {
content.append(line).append("\n");
}
} catch (IOException e) {
System.err.println("读取文本文件异常: " + e.getMessage());
}
return content.toString();
}
/**
* 使用BufferedReader按行读取大文件
*/
public static void readLargeFileByLines(String fileName) {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(fileName), StandardCharsets.UTF_8))) {
String line;
int lineNumber = 1;
while ((line = reader.readLine()) != null) {
System.out.println("第" + lineNumber + "行: " + line);
lineNumber++;
}
} catch (IOException e) {
System.err.println("按行读取文件异常: " + e.getMessage());
}
}
/**
* 使用PrintWriter进行格式化输出
*/
public static void writeFormattedText(String fileName) {
try (PrintWriter writer = new PrintWriter(
new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8))) {
writer.printf("姓名: %s%n", "张三");
writer.printf("年龄: %d%n", 25);
writer.printf("薪资: %.2f%n", 8500.50);
writer.println("这是格式化输出的内容");
System.out.println("格式化文本写入完成");
} catch (IOException e) {
System.err.println("格式化写入异常: " + e.getMessage());
}
}
}
4. 文件管理工具 - FileManager.java
package file;
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FileManager {
/**
* 创建目录
*/
public static boolean createDirectory(String directoryPath) {
try {
Path path = Paths.get(directoryPath);
if (!Files.exists(path)) {
Files.createDirectories(path);
System.out.println("目录创建成功: " + directoryPath);
return true;
} else {
System.out.println("目录已存在: " + directoryPath);
return false;
}
} catch (IOException e) {
System.err.println("创建目录失败: " + e.getMessage());
return false;
}
}
/**
* 列出目录下的所有文件
*/
public static void listFiles(String directoryPath) {
try (Stream<Path> paths = Files.list(Paths.get(directoryPath))) {
List<Path> files = paths.collect(Collectors.toList());
System.out.println("目录 " + directoryPath + " 下的文件:");
files.forEach(System.out::println);
} catch (IOException e) {
System.err.println("列出文件异常: " + e.getMessage());
}
}
/**
* 递归遍历目录树
*/
public static void walkDirectoryTree(String directoryPath) {
try {
Files.walkFileTree(Paths.get(directoryPath), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println("文件: " + file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
System.out.println("目录: " + dir);
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
System.err.println("遍历目录树异常: " + e.getMessage());
}
}
/**
* 获取文件信息
*/
public static void getFileInfo(String filePath) {
try {
Path path = Paths.get(filePath);
if (Files.exists(path)) {
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println("文件名: " + path.getFileName());
System.out.println("文件大小: " + attrs.size() + " 字节");
System.out.println("创建时间: " + attrs.creationTime());
System.out.println("最后修改时间: " + attrs.lastModifiedTime());
System.out.println("是否为目录: " + attrs.isDirectory());
System.out.println("是否为文件: " + attrs.isRegularFile());
} else {
System.out.println("文件不存在: " + filePath);
}
} catch (IOException e) {
System.err.println("获取文件信息异常: " + e.getMessage());
}
}
/**
* 删除文件或目录
*/
public static boolean deleteFileOrDirectory(String path) {
try {
Path filePath = Paths.get(path);
if (Files.exists(filePath)) {
if (Files.isDirectory(filePath)) {
// 递归删除目录
Files.walkFileTree(filePath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
} else {
Files.delete(filePath);
}
System.out.println("删除成功: " + path);
return true;
} else {
System.out.println("路径不存在: " + path);
return false;
}
} catch (IOException e) {
System.err.println("删除失败: " + e.getMessage());
return false;
}
}
}
5. 序列化操作 - SerializationDemo.java
package serialization;
import java.io.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
public class SerializationDemo {
/**
* 对象序列化到文件
*/
public static void serializeObject(Object obj, String fileName) {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) {
oos.writeObject(obj);
System.out.println("对象序列化完成: " + fileName);
} catch (IOException e) {
System.err.println("序列化异常: " + e.getMessage());
}
}
/**
* 从文件反序列化对象
*/
public static Object deserializeObject(String fileName) {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) {
Object obj = ois.readObject();
System.out.println("对象反序列化完成: " + fileName);
return obj;
} catch (IOException | ClassNotFoundException e) {
System.err.println("反序列化异常: " + e.getMessage());
return null;
}
}
/**
* 序列化员工列表
*/
public static void serializeEmployeeList(List<Employee> employees, String fileName) {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) {
oos.writeObject(employees);
System.out.println("员工列表序列化完成: " + fileName);
} catch (IOException e) {
System.err.println("员工列表序列化异常: " + e.getMessage());
}
}
/**
* 反序列化员工列表
*/
public static List<Employee> deserializeEmployeeList(String fileName) {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) {
@SuppressWarnings("unchecked")
List<Employee> employees = (List<Employee>) ois.readObject();
System.out.println("员工列表反序列化完成: " + fileName);
return employees;
} catch (IOException | ClassNotFoundException e) {
System.err.println("员工列表反序列化异常: " + e.getMessage());
return new ArrayList<>();
}
}
/**
* 演示序列化过程
*/
public static void demonstrateSerialization() {
// 创建员工对象
List<Employee> employees = new ArrayList<>();
employees.add(new Employee(1L, "张三", "技术部", 15000.0, LocalDate.now()));
employees.add(new Employee(2L, "李四", "市场部", 12000.0, LocalDate.now().minusDays(30)));
employees.add(new Employee(3L, "王五", "人事部", 10000.0, LocalDate.now().minusDays(60)));
// 序列化
String fileName = "employees.ser";
serializeEmployeeList(employees, fileName);
// 反序列化
List<Employee> deserializedEmployees = deserializeEmployeeList(fileName);
// 显示结果
System.out.println("反序列化后的员工列表:");
deserializedEmployees.forEach(System.out::println);
}
}
6. 自定义序列化 - CustomSerializationDemo.java
package serialization;
import java.io.*;
import java.time.LocalDate;
public class CustomSerializationDemo implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private transient String password; // 不序列化
private LocalDate registrationDate;
public CustomSerializationDemo(String name, int age, String password, LocalDate registrationDate) {
this.name = name;
this.age = age;
this.password = password;
this.registrationDate = registrationDate;
}
/**
* 自定义序列化方法
*/
private void writeObject(ObjectOutputStream oos) throws IOException {
// 执行默认序列化
oos.defaultWriteObject();
// 自定义序列化password字段
oos.writeObject(password != null ? password : "");
System.out.println("执行自定义序列化");
}
/**
* 自定义反序列化方法
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// 执行默认反序列化
ois.defaultReadObject();
// 自定义反序列化password字段
password = (String) ois.readObject();
if (password.isEmpty()) {
password = null;
}
System.out.println("执行自定义反序列化");
}
// Getters
public String getName() { return name; }
public int getAge() { return age; }
public String getPassword() { return password; }
public LocalDate getRegistrationDate() { return registrationDate; }
@Override
public String toString() {
return "CustomSerializationDemo{" +
"name='" + name + '\'' +
", age=" + age +
", password='" + (password != null ? "[PROTECTED]" : "null") + '\'' +
", registrationDate=" + registrationDate +
'}';
}
/**
* 演示自定义序列化
*/
public static void demonstrateCustomSerialization() {
// 创建对象
CustomSerializationDemo obj = new CustomSerializationDemo(
"测试用户", 25, "secret123", LocalDate.now());
System.out.println("序列化前的对象:");
System.out.println(obj);
// 序列化
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("custom.ser"))) {
oos.writeObject(obj);
} catch (IOException e) {
System.err.println("序列化异常: " + e.getMessage());
return;
}
// 反序列化
CustomSerializationDemo deserializedObj;
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("custom.ser"))) {
deserializedObj = (CustomSerializationDemo) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
System.err.println("反序列化异常: " + e.getMessage());
return;
}
System.out.println("反序列化后的对象:");
System.out.println(deserializedObj);
}
}
7. 文件操作演示 - FileOperationsDemo.java
package file;
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
import java.util.stream.Collectors;
public class FileOperationsDemo {
/**
* 使用传统IO创建和读取文件
*/
public static void traditionalFileOperations() {
String fileName = "traditional.txt";
// 写入文件
try (FileWriter writer = new FileWriter(fileName)) {
writer.write("这是传统IO写入的内容\n");
writer.write("第二行内容\n");
writer.write("第三行内容\n");
System.out.println("传统IO写入完成");
} catch (IOException e) {
System.err.println("写入文件异常: " + e.getMessage());
}
// 读取文件
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
String line;
System.out.println("传统IO读取内容:");
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.err.println("读取文件异常: " + e.getMessage());
}
}
/**
* 使用NIO.2创建和读取文件
*/
public static void nioFileOperations() {
Path path = Paths.get("nio.txt");
// 写入文件
try {
List<String> lines = List.of("这是NIO写入的内容", "第二行内容", "第三行内容");
Files.write(path, lines);
System.out.println("NIO写入完成");
} catch (IOException e) {
System.err.println("NIO写入异常: " + e.getMessage());
}
// 读取文件
try {
List<String> lines = Files.readAllLines(path);
System.out.println("NIO读取内容:");
lines.forEach(System.out::println);
} catch (IOException e) {
System.err.println("NIO读取异常: " + e.getMessage());
}
}
/**
* 文件复制操作对比
*/
public static void compareFileCopyMethods() {
String sourceFile = "source.txt";
String targetFile1 = "target1.txt";
String targetFile2 = "target2.txt";
// 创建源文件
try {
Files.write(Paths.get(sourceFile),
"这是测试文件内容\n用于测试不同的复制方法\n包含多行数据".getBytes());
} catch (IOException e) {
System.err.println("创建源文件异常: " + e.getMessage());
return;
}
// 方法1: Files.copy()
try {
long startTime = System.currentTimeMillis();
Files.copy(Paths.get(sourceFile), Paths.get(targetFile1),
StandardCopyOption.REPLACE_EXISTING);
long endTime = System.currentTimeMillis();
System.out.println("Files.copy() 耗时: " + (endTime - startTime) + "ms");
} catch (IOException e) {
System.err.println("Files.copy() 异常: " + e.getMessage());
}
// 方法2: 传统流复制
try {
long startTime = System.currentTimeMillis();
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFile2))) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
}
long endTime = System.currentTimeMillis();
System.out.println("传统流复制 耗时: " + (endTime - startTime) + "ms");
} catch (IOException e) {
System.err.println("传统流复制异常: " + e.getMessage());
}
}
/**
* 监控目录变化
*/
public static void watchDirectory(String directoryPath) {
try {
Path path = Paths.get(directoryPath);
if (!Files.exists(path)) {
Files.createDirectories(path);
}
WatchService watchService = FileSystems.getDefault().newWatchService();
path.register(watchService,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);
System.out.println("开始监控目录: " + directoryPath);
System.out.println("按Ctrl+C停止监控");
// 简单监控示例(实际应用中应使用单独线程)
WatchKey key = watchService.poll();
if (key != null) {
for (WatchEvent<?> event : key.pollEvents()) {
System.out.println("事件类型: " + event.kind() + ", 文件: " + event.context());
}
key.reset();
}
} catch (IOException e) {
System.err.println("目录监控异常: " + e.getMessage());
}
}
}
8. 主应用程序 - MainApplication.java
import file.*;
import io.*;
import serialization.*;
import java.time.LocalDate;
import java.util.Arrays;
public class MainApplication {
public static void main(String[] args) {
System.out.println("=== IO流、文件操作、序列化演示程序 ===\n");
// 1. 字节流操作演示
demonstrateByteStreamOperations();
// 2. 字符流操作演示
demonstrateCharacterStreamOperations();
// 3. 文件管理操作演示
demonstrateFileManagement();
// 4. 序列化操作演示
demonstrateSerializationOperations();
// 5. 自定义序列化演示
demonstrateCustomSerialization();
// 6. 文件操作对比演示
demonstrateFileOperations();
}
private static void demonstrateByteStreamOperations() {
System.out.println("1. 字节流操作演示");
System.out.println("-------------------");
// 创建测试文件
CharacterStreamDemo.writeTextFile("test_input.txt",
"这是一个测试文件\n用于演示字节流操作\n包含多行内容");
// 字节流复制
ByteStreamDemo.copyFileWithByteStream("test_input.txt", "byte_copy.txt");
// 缓冲字节流复制
ByteStreamDemo.copyFileWithBufferedByteStream("test_input.txt", "buffered_copy.txt");
System.out.println();
}
private static void demonstrateCharacterStreamOperations() {
System.out.println("2. 字符流操作演示");
System.out.println("-------------------");
// 写入文本文件
CharacterStreamDemo.writeTextFile("character_test.txt",
"字符流测试内容\n第二行\n第三行\n第四行内容");
// 读取文本文件
String content = CharacterStreamDemo.readTextFile("character_test.txt");
System.out.println("读取的文件内容:");
System.out.println(content);
// 格式化写入
CharacterStreamDemo.writeFormattedText("formatted_output.txt");
System.out.println();
}
private static void demonstrateFileManagement() {
System.out.println("3. 文件管理操作演示");
System.out.println("-------------------");
// 创建目录
FileManager.createDirectory("test_directory");
FileManager.createDirectory("test_directory/sub_directory");
// 列出文件
FileManager.listFiles(".");
// 获取文件信息
FileManager.getFileInfo("character_test.txt");
System.out.println();
}
private static void demonstrateSerializationOperations() {
System.out.println("4. 序列化操作演示");
System.out.println("-------------------");
SerializationDemo.demonstrateSerialization();
System.out.println();
}
private static void demonstrateCustomSerialization() {
System.out.println("5. 自定义序列化演示");
System.out.println("-------------------");
CustomSerializationDemo.demonstrateCustomSerialization();
System.out.println();
}
private static void demonstrateFileOperations() {
System.out.println("6. 文件操作对比演示");
System.out.println("-------------------");
FileOperationsDemo.traditionalFileOperations();
FileOperationsDemo.nioFileOperations();
FileOperationsDemo.compareFileCopyMethods();
System.out.println();
}
}
项目特点
1. 技术覆盖全面
- 字节流操作:
FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream - 字符流操作:
FileReader、FileWriter、BufferedReader、BufferedWriter、PrintWriter - 文件管理:
Files、Paths、Path、WatchService - 序列化:
ObjectOutputStream、ObjectInputStream、自定义序列化
2. 实际应用场景
- 文件复制和备份
- 文本文件读写处理
- 二进制文件操作
- 对象持久化存储
- 目录遍历和监控
- 大文件处理优化
3. 最佳实践展示
- 资源管理:使用try-with-resources确保资源正确关闭
- 异常处理:完善的IO异常处理机制
- 性能优化:缓冲流提高读写效率
- 编码处理:明确指定字符编码(UTF-8)
- 类型安全:泛型和类型检查
这个项目涵盖了Java IO操作的各个方面,提供了完整的可运行示例,适合学习和实际项目参考。