14.1 I/O基础概念
14.1.1 I/O概述
I/O(Input/Output)是计算机程序与外部世界进行数据交换的重要机制。Java提供了丰富的I/O API来处理各种数据源和目标,包括文件、网络连接、内存缓冲区等。
I/O的分类: - 按数据流向:输入流(Input)、输出流(Output) - 按数据类型:字节流(Byte Stream)、字符流(Character Stream) - 按功能特点:节点流(Node Stream)、处理流(Processing Stream)
import java.io.*;
import java.nio.file.*;
import java.util.*;
// I/O基础概念演示
public class IOBasicsDemo {
public static void main(String[] args) {
// I/O流的层次结构演示
demonstrateStreamHierarchy();
// 文件系统基础操作
demonstrateFileSystemBasics();
// I/O异常处理
demonstrateIOExceptionHandling();
}
// I/O流的层次结构演示
public static void demonstrateStreamHierarchy() {
System.out.println("=== I/O流的层次结构 ===");
// 字节流基类
System.out.println("字节流基类:");
System.out.println(" InputStream - 字节输入流的抽象基类");
System.out.println(" OutputStream - 字节输出流的抽象基类");
// 字符流基类
System.out.println("\n字符流基类:");
System.out.println(" Reader - 字符输入流的抽象基类");
System.out.println(" Writer - 字符输出流的抽象基类");
// 常用实现类
System.out.println("\n常用字节流实现类:");
System.out.println(" FileInputStream/FileOutputStream - 文件字节流");
System.out.println(" ByteArrayInputStream/ByteArrayOutputStream - 字节数组流");
System.out.println(" BufferedInputStream/BufferedOutputStream - 缓冲字节流");
System.out.println("\n常用字符流实现类:");
System.out.println(" FileReader/FileWriter - 文件字符流");
System.out.println(" StringReader/StringWriter - 字符串流");
System.out.println(" BufferedReader/BufferedWriter - 缓冲字符流");
}
// 文件系统基础操作
public static void demonstrateFileSystemBasics() {
System.out.println("\n=== 文件系统基础操作 ===");
// File类基础操作
File file = new File("test.txt");
System.out.println("文件名: " + file.getName());
System.out.println("绝对路径: " + file.getAbsolutePath());
System.out.println("父目录: " + file.getParent());
System.out.println("是否存在: " + file.exists());
System.out.println("是否为文件: " + file.isFile());
System.out.println("是否为目录: " + file.isDirectory());
// 目录操作
File directory = new File("testDir");
if (!directory.exists()) {
boolean created = directory.mkdir();
System.out.println("创建目录: " + created);
}
// 列出目录内容
File currentDir = new File(".");
String[] files = currentDir.list();
if (files != null) {
System.out.println("\n当前目录内容:");
for (String fileName : files) {
System.out.println(" " + fileName);
}
}
// 文件属性
if (file.exists()) {
System.out.println("\n文件属性:");
System.out.println(" 大小: " + file.length() + " 字节");
System.out.println(" 最后修改时间: " + new Date(file.lastModified()));
System.out.println(" 可读: " + file.canRead());
System.out.println(" 可写: " + file.canWrite());
System.out.println(" 可执行: " + file.canExecute());
}
}
// I/O异常处理
public static void demonstrateIOExceptionHandling() {
System.out.println("\n=== I/O异常处理 ===");
// 传统的try-catch-finally
FileInputStream fis = null;
try {
fis = new FileInputStream("nonexistent.txt");
// 读取操作...
} catch (FileNotFoundException e) {
System.out.println("文件未找到: " + e.getMessage());
} catch (IOException e) {
System.out.println("I/O异常: " + e.getMessage());
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
System.out.println("关闭流时发生异常: " + e.getMessage());
}
}
}
// try-with-resources(推荐方式)
try (FileInputStream fis2 = new FileInputStream("nonexistent.txt")) {
// 读取操作...
} catch (FileNotFoundException e) {
System.out.println("使用try-with-resources处理文件未找到: " + e.getMessage());
} catch (IOException e) {
System.out.println("使用try-with-resources处理I/O异常: " + e.getMessage());
}
// 多个资源的try-with-resources
try (FileInputStream input = new FileInputStream("input.txt");
FileOutputStream output = new FileOutputStream("output.txt")) {
// 复制操作...
} catch (IOException e) {
System.out.println("多资源操作异常: " + e.getMessage());
}
}
}
14.5 对象序列化
14.5.1 基础序列化
import java.io.*;
import java.util.*;
// 序列化演示类
class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private transient String password; // transient字段不会被序列化
private static String country = "China"; // static字段不会被序列化
public Person(String name, int age, String password) {
this.name = name;
this.age = age;
this.password = password;
}
// getter和setter方法
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public static String getCountry() { return country; }
public static void setCountry(String country) { Person.country = country; }
@Override
public String toString() {
return String.format("Person{name='%s', age=%d, password='%s', country='%s'}",
name, age, password, country);
}
}
// 自定义序列化的类
class Student implements Serializable {
private static final long serialVersionUID = 2L;
private String name;
private int score;
private Date enrollDate;
public Student(String name, int score) {
this.name = name;
this.score = score;
this.enrollDate = new Date();
}
// 自定义序列化方法
private void writeObject(ObjectOutputStream out) throws IOException {
System.out.println("执行自定义序列化: " + name);
out.defaultWriteObject(); // 执行默认序列化
out.writeUTF("额外的序列化数据"); // 写入额外数据
}
// 自定义反序列化方法
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
System.out.println("执行自定义反序列化");
in.defaultReadObject(); // 执行默认反序列化
String extraData = in.readUTF(); // 读取额外数据
System.out.println("读取到额外数据: " + extraData);
}
// getter方法
public String getName() { return name; }
public int getScore() { return score; }
public Date getEnrollDate() { return enrollDate; }
@Override
public String toString() {
return String.format("Student{name='%s', score=%d, enrollDate=%s}",
name, score, enrollDate);
}
}
// 对象序列化演示
public class SerializationDemo {
public static void main(String[] args) {
// 基础序列化演示
demonstrateBasicSerialization();
// 集合序列化演示
demonstrateCollectionSerialization();
// 自定义序列化演示
demonstrateCustomSerialization();
// 序列化版本控制
demonstrateVersionControl();
}
// 基础序列化演示
public static void demonstrateBasicSerialization() {
System.out.println("=== 基础序列化演示 ===");
String fileName = "person.ser";
// 创建对象
Person person = new Person("张三", 25, "secret123");
System.out.println("原始对象: " + person);
// 序列化对象
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(fileName))) {
oos.writeObject(person);
System.out.println("对象序列化完成");
} catch (IOException e) {
System.out.println("序列化失败: " + e.getMessage());
return;
}
// 反序列化对象
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(fileName))) {
Person deserializedPerson = (Person) ois.readObject();
System.out.println("反序列化对象: " + deserializedPerson);
// 验证transient和static字段
System.out.println("\n字段验证:");
System.out.println(" name: " + deserializedPerson.getName());
System.out.println(" age: " + deserializedPerson.getAge());
System.out.println(" password (transient): " + deserializedPerson.getPassword());
System.out.println(" country (static): " + Person.getCountry());
} catch (IOException | ClassNotFoundException e) {
System.out.println("反序列化失败: " + e.getMessage());
}
// 检查文件大小
File serFile = new File(fileName);
if (serFile.exists()) {
System.out.println("\n序列化文件大小: " + serFile.length() + " 字节");
}
}
// 集合序列化演示
public static void demonstrateCollectionSerialization() {
System.out.println("\n=== 集合序列化演示 ===");
String fileName = "collection.ser";
// 创建集合
List<Person> personList = Arrays.asList(
new Person("Alice", 30, "pass1"),
new Person("Bob", 25, "pass2"),
new Person("Charlie", 35, "pass3")
);
Map<String, Integer> scoreMap = new HashMap<>();
scoreMap.put("Math", 95);
scoreMap.put("English", 87);
scoreMap.put("Science", 92);
System.out.println("原始集合:");
System.out.println(" 人员列表: " + personList.size() + " 个人员");
System.out.println(" 成绩映射: " + scoreMap);
// 序列化集合
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(fileName))) {
oos.writeObject(personList);
oos.writeObject(scoreMap);
System.out.println("\n集合序列化完成");
} catch (IOException e) {
System.out.println("集合序列化失败: " + e.getMessage());
return;
}
// 反序列化集合
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(fileName))) {
@SuppressWarnings("unchecked")
List<Person> deserializedList = (List<Person>) ois.readObject();
@SuppressWarnings("unchecked")
Map<String, Integer> deserializedMap = (Map<String, Integer>) ois.readObject();
System.out.println("\n反序列化集合:");
System.out.println(" 人员列表:");
deserializedList.forEach(person -> System.out.println(" " + person));
System.out.println(" 成绩映射: " + deserializedMap);
} catch (IOException | ClassNotFoundException e) {
System.out.println("集合反序列化失败: " + e.getMessage());
}
}
// 自定义序列化演示
public static void demonstrateCustomSerialization() {
System.out.println("\n=== 自定义序列化演示 ===");
String fileName = "student.ser";
// 创建学生对象
Student student = new Student("李四", 88);
System.out.println("原始学生对象: " + student);
// 序列化
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(fileName))) {
oos.writeObject(student);
System.out.println("\n学生对象序列化完成");
} catch (IOException e) {
System.out.println("学生对象序列化失败: " + e.getMessage());
return;
}
// 反序列化
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(fileName))) {
Student deserializedStudent = (Student) ois.readObject();
System.out.println("\n反序列化学生对象: " + deserializedStudent);
} catch (IOException | ClassNotFoundException e) {
System.out.println("学生对象反序列化失败: " + e.getMessage());
}
}
// 序列化版本控制
public static void demonstrateVersionControl() {
System.out.println("\n=== 序列化版本控制 ===");
System.out.println("Person类的serialVersionUID: " + getSerialVersionUID(Person.class));
System.out.println("Student类的serialVersionUID: " + getSerialVersionUID(Student.class));
// 演示版本兼容性
System.out.println("\n版本兼容性说明:");
System.out.println(" - serialVersionUID相同: 兼容");
System.out.println(" - serialVersionUID不同: 抛出InvalidClassException");
System.out.println(" - 未定义serialVersionUID: 由JVM自动生成,类结构变化时会改变");
}
private static long getSerialVersionUID(Class<?> clazz) {
try {
return clazz.getDeclaredField("serialVersionUID").getLong(null);
} catch (Exception e) {
return -1; // 未定义或获取失败
}
}
}
14.6 NIO编程基础
14.6.1 Channel和Buffer
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
import java.util.*;
// NIO编程演示
public class NIODemo {
public static void main(String[] args) {
// Buffer操作演示
demonstrateBuffer();
// Channel操作演示
demonstrateChannel();
// 文件Channel操作
demonstrateFileChannel();
// 内存映射文件
demonstrateMemoryMappedFile();
}
// Buffer操作演示
public static void demonstrateBuffer() {
System.out.println("=== Buffer操作演示 ===");
// ByteBuffer操作
ByteBuffer buffer = ByteBuffer.allocate(10);
System.out.println("初始状态: " + bufferInfo(buffer));
// 写入数据
buffer.put((byte) 'H');
buffer.put((byte) 'e');
buffer.put((byte) 'l');
buffer.put((byte) 'l');
buffer.put((byte) 'o');
System.out.println("写入Hello后: " + bufferInfo(buffer));
// 切换到读模式
buffer.flip();
System.out.println("flip后: " + bufferInfo(buffer));
// 读取数据
System.out.println("\n读取数据:");
while (buffer.hasRemaining()) {
byte b = buffer.get();
System.out.print((char) b);
}
System.out.println();
System.out.println("读取完成后: " + bufferInfo(buffer));
// 重置和清空
buffer.rewind(); // 重置position到0
System.out.println("rewind后: " + bufferInfo(buffer));
buffer.clear(); // 清空buffer
System.out.println("clear后: " + bufferInfo(buffer));
// 直接Buffer vs 非直接Buffer
demonstrateDirectBuffer();
}
private static String bufferInfo(Buffer buffer) {
return String.format("position=%d, limit=%d, capacity=%d, remaining=%d",
buffer.position(), buffer.limit(), buffer.capacity(), buffer.remaining());
}
private static void demonstrateDirectBuffer() {
System.out.println("\n直接Buffer vs 非直接Buffer:");
// 非直接Buffer
ByteBuffer heapBuffer = ByteBuffer.allocate(1024);
System.out.println("堆Buffer - isDirect: " + heapBuffer.isDirect());
// 直接Buffer
ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024);
System.out.println("直接Buffer - isDirect: " + directBuffer.isDirect());
// 性能测试
int iterations = 100000;
byte[] data = "Hello NIO Buffer Performance Test".getBytes();
// 堆Buffer性能
long startTime = System.nanoTime();
for (int i = 0; i < iterations; i++) {
heapBuffer.clear();
heapBuffer.put(data);
heapBuffer.flip();
}
long heapTime = System.nanoTime() - startTime;
// 直接Buffer性能
startTime = System.nanoTime();
for (int i = 0; i < iterations; i++) {
directBuffer.clear();
directBuffer.put(data);
directBuffer.flip();
}
long directTime = System.nanoTime() - startTime;
System.out.println("性能测试 (" + iterations + " 次操作):");
System.out.println(" 堆Buffer: " + heapTime / 1000000 + "ms");
System.out.println(" 直接Buffer: " + directTime / 1000000 + "ms");
}
// Channel操作演示
public static void demonstrateChannel() {
System.out.println("\n=== Channel操作演示 ===");
String fileName = "nio_test.txt";
String content = "这是NIO Channel测试内容\n包含多行文本\n用于演示Channel操作";
// 使用Channel写入文件
try (FileChannel writeChannel = FileChannel.open(
Paths.get(fileName),
StandardOpenOption.CREATE,
StandardOpenOption.WRITE,
StandardOpenOption.TRUNCATE_EXISTING)) {
ByteBuffer writeBuffer = ByteBuffer.wrap(content.getBytes("UTF-8"));
int bytesWritten = writeChannel.write(writeBuffer);
System.out.println("写入字节数: " + bytesWritten);
System.out.println("Channel位置: " + writeChannel.position());
System.out.println("Channel大小: " + writeChannel.size());
} catch (IOException e) {
System.out.println("Channel写入失败: " + e.getMessage());
return;
}
// 使用Channel读取文件
try (FileChannel readChannel = FileChannel.open(
Paths.get(fileName), StandardOpenOption.READ)) {
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
int bytesRead = readChannel.read(readBuffer);
readBuffer.flip();
String readContent = new String(readBuffer.array(), 0, bytesRead, "UTF-8");
System.out.println("\n读取内容:");
System.out.println(readContent);
System.out.println("读取字节数: " + bytesRead);
} catch (IOException e) {
System.out.println("Channel读取失败: " + e.getMessage());
}
}
// 文件Channel操作
public static void demonstrateFileChannel() {
System.out.println("\n=== 文件Channel操作 ===");
String sourceFile = "source_channel.txt";
String targetFile = "target_channel.txt";
// 创建源文件
try {
Files.write(Paths.get(sourceFile),
"这是用于Channel复制测试的源文件内容\n包含多行数据\n用于演示文件传输".getBytes("UTF-8"));
} catch (IOException e) {
System.out.println("创建源文件失败: " + e.getMessage());
return;
}
// 使用transferTo方法复制文件
try (FileChannel sourceChannel = FileChannel.open(
Paths.get(sourceFile), StandardOpenOption.READ);
FileChannel targetChannel = FileChannel.open(
Paths.get(targetFile),
StandardOpenOption.CREATE,
StandardOpenOption.WRITE,
StandardOpenOption.TRUNCATE_EXISTING)) {
long startTime = System.nanoTime();
long bytesTransferred = sourceChannel.transferTo(0, sourceChannel.size(), targetChannel);
long transferTime = System.nanoTime() - startTime;
System.out.println("transferTo复制:");
System.out.println(" 传输字节数: " + bytesTransferred);
System.out.println(" 传输时间: " + transferTime / 1000000 + "ms");
} catch (IOException e) {
System.out.println("transferTo复制失败: " + e.getMessage());
}
// 验证复制结果
try {
String sourceContent = Files.readString(Paths.get(sourceFile));
String targetContent = Files.readString(Paths.get(targetFile));
boolean contentMatch = sourceContent.equals(targetContent);
System.out.println(" 内容匹配: " + contentMatch);
} catch (IOException e) {
System.out.println("验证复制结果失败: " + e.getMessage());
}
// Channel位置操作
demonstrateChannelPosition(sourceFile);
}
private static void demonstrateChannelPosition(String fileName) {
System.out.println("\nChannel位置操作:");
try (FileChannel channel = FileChannel.open(
Paths.get(fileName), StandardOpenOption.READ)) {
System.out.println(" 初始位置: " + channel.position());
System.out.println(" 文件大小: " + channel.size());
// 移动到文件中间
long middlePosition = channel.size() / 2;
channel.position(middlePosition);
System.out.println(" 移动到中间位置: " + channel.position());
// 从中间位置读取
ByteBuffer buffer = ByteBuffer.allocate(20);
int bytesRead = channel.read(buffer);
buffer.flip();
String content = new String(buffer.array(), 0, bytesRead, "UTF-8");
System.out.println(" 从中间读取内容: " + content.replace("\n", "\\n"));
} catch (IOException e) {
System.out.println("Channel位置操作失败: " + e.getMessage());
}
}
// 内存映射文件
public static void demonstrateMemoryMappedFile() {
System.out.println("\n=== 内存映射文件 ===");
String fileName = "memory_mapped.txt";
String content = "这是内存映射文件测试内容,用于演示MappedByteBuffer的使用";
try {
// 创建测试文件
Files.write(Paths.get(fileName), content.getBytes("UTF-8"));
// 内存映射文件
try (RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
FileChannel channel = raf.getChannel()) {
// 映射整个文件到内存
MappedByteBuffer mappedBuffer = channel.map(
FileChannel.MapMode.READ_WRITE, 0, channel.size());
System.out.println("文件映射信息:");
System.out.println(" 映射大小: " + mappedBuffer.capacity());
System.out.println(" 是否为直接Buffer: " + mappedBuffer.isDirect());
// 读取映射内容
byte[] data = new byte[mappedBuffer.remaining()];
mappedBuffer.get(data);
String mappedContent = new String(data, "UTF-8");
System.out.println(" 映射内容: " + mappedContent);
// 修改映射内容
mappedBuffer.position(0);
String newContent = "修改后的内容: " + System.currentTimeMillis();
mappedBuffer.put(newContent.getBytes("UTF-8"));
// 强制同步到磁盘
mappedBuffer.force();
System.out.println(" 内容已修改并同步到磁盘");
}
// 验证修改结果
String modifiedContent = Files.readString(Paths.get(fileName));
System.out.println(" 验证修改结果: " + modifiedContent.substring(0, Math.min(30, modifiedContent.length())));
} catch (IOException e) {
System.out.println("内存映射文件操作失败: " + e.getMessage());
}
// 性能对比:内存映射 vs 传统I/O
performanceComparisonMappedVsTraditional();
}
private static void performanceComparisonMappedVsTraditional() {
System.out.println("\n性能对比: 内存映射 vs 传统I/O");
String fileName = "performance_test.dat";
int fileSize = 1024 * 1024; // 1MB
byte[] testData = new byte[fileSize];
Arrays.fill(testData, (byte) 'A');
try {
// 创建测试文件
Files.write(Paths.get(fileName), testData);
// 传统I/O读取
long startTime = System.nanoTime();
try (FileInputStream fis = new FileInputStream(fileName)) {
byte[] buffer = new byte[8192];
int totalBytes = 0;
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
totalBytes += bytesRead;
}
}
long traditionalTime = System.nanoTime() - startTime;
// 内存映射读取
startTime = System.nanoTime();
try (RandomAccessFile raf = new RandomAccessFile(fileName, "r");
FileChannel channel = raf.getChannel()) {
MappedByteBuffer mappedBuffer = channel.map(
FileChannel.MapMode.READ_ONLY, 0, channel.size());
int totalBytes = 0;
while (mappedBuffer.hasRemaining()) {
mappedBuffer.get();
totalBytes++;
}
}
long mappedTime = System.nanoTime() - startTime;
System.out.println(" 文件大小: " + fileSize + " 字节");
System.out.println(" 传统I/O时间: " + traditionalTime / 1000000 + "ms");
System.out.println(" 内存映射时间: " + mappedTime / 1000000 + "ms");
System.out.println(" 性能提升: " + (traditionalTime / (double) mappedTime) + "倍");
} catch (IOException e) {
System.out.println("性能对比测试失败: " + e.getMessage());
}
}
}
14.7 文件压缩和解压
14.7.1 ZIP文件操作
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.zip.*;
// 文件压缩和解压演示
public class CompressionDemo {
public static void main(String[] args) {
// ZIP压缩演示
demonstrateZipCompression();
// ZIP解压演示
demonstrateZipExtraction();
// GZIP压缩演示
demonstrateGzipCompression();
// 压缩性能测试
demonstrateCompressionPerformance();
}
// ZIP压缩演示
public static void demonstrateZipCompression() {
System.out.println("=== ZIP压缩演示 ===");
// 创建测试文件
createTestFiles();
String zipFileName = "test_archive.zip";
String[] filesToCompress = {"test1.txt", "test2.txt", "test3.txt"};
try (ZipOutputStream zos = new ZipOutputStream(
new FileOutputStream(zipFileName))) {
for (String fileName : filesToCompress) {
File file = new File(fileName);
if (!file.exists()) continue;
// 添加ZIP条目
ZipEntry zipEntry = new ZipEntry(fileName);
zos.putNextEntry(zipEntry);
// 读取文件并写入ZIP
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
zos.write(buffer, 0, bytesRead);
}
}
zos.closeEntry();
System.out.println("已压缩文件: " + fileName);
}
System.out.println("ZIP压缩完成: " + zipFileName);
} catch (IOException e) {
System.out.println("ZIP压缩失败: " + e.getMessage());
}
// 显示压缩信息
displayCompressionInfo(filesToCompress, zipFileName);
}
private static void createTestFiles() {
String[] fileNames = {"test1.txt", "test2.txt", "test3.txt"};
String[] contents = {
"这是第一个测试文件\n包含一些文本内容\n用于压缩测试",
"第二个文件的内容\n包含更多的文本\n用于演示ZIP压缩功能\n重复内容重复内容重复内容",
"第三个文件\n包含大量重复文本\n" + "重复行\n".repeat(100)
};
for (int i = 0; i < fileNames.length; i++) {
try {
Files.write(Paths.get(fileNames[i]), contents[i].getBytes("UTF-8"));
} catch (IOException e) {
System.out.println("创建测试文件失败: " + fileNames[i]);
}
}
}
private static void displayCompressionInfo(String[] originalFiles, String zipFile) {
try {
long originalSize = 0;
for (String fileName : originalFiles) {
File file = new File(fileName);
if (file.exists()) {
originalSize += file.length();
}
}
long compressedSize = new File(zipFile).length();
double compressionRatio = (1.0 - (double) compressedSize / originalSize) * 100;
System.out.println("\n压缩信息:");
System.out.println(" 原始大小: " + originalSize + " 字节");
System.out.println(" 压缩大小: " + compressedSize + " 字节");
System.out.println(" 压缩率: " + String.format("%.1f%%", compressionRatio));
} catch (Exception e) {
System.out.println("获取压缩信息失败: " + e.getMessage());
}
}
// ZIP解压演示
public static void demonstrateZipExtraction() {
System.out.println("\n=== ZIP解压演示 ===");
String zipFileName = "test_archive.zip";
String extractDir = "extracted";
// 创建解压目录
try {
Files.createDirectories(Paths.get(extractDir));
} catch (IOException e) {
System.out.println("创建解压目录失败: " + e.getMessage());
return;
}
try (ZipInputStream zis = new ZipInputStream(
new FileInputStream(zipFileName))) {
ZipEntry zipEntry;
while ((zipEntry = zis.getNextEntry()) != null) {
String fileName = zipEntry.getName();
File extractedFile = new File(extractDir, fileName);
System.out.println("正在解压: " + fileName);
// 创建父目录
extractedFile.getParentFile().mkdirs();
// 解压文件
try (FileOutputStream fos = new FileOutputStream(extractedFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = zis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
}
zis.closeEntry();
// 显示文件信息
System.out.println(" 解压大小: " + extractedFile.length() + " 字节");
System.out.println(" 压缩大小: " + zipEntry.getCompressedSize() + " 字节");
System.out.println(" 压缩方法: " + getCompressionMethod(zipEntry.getMethod()));
}
System.out.println("ZIP解压完成");
} catch (IOException e) {
System.out.println("ZIP解压失败: " + e.getMessage());
}
// 验证解压结果
verifyExtraction(extractDir);
}
private static String getCompressionMethod(int method) {
switch (method) {
case ZipEntry.STORED: return "STORED (无压缩)";
case ZipEntry.DEFLATED: return "DEFLATED (压缩)";
default: return "未知方法 (" + method + ")";
}
}
private static void verifyExtraction(String extractDir) {
System.out.println("\n验证解压结果:");
try (Stream<Path> paths = Files.walk(Paths.get(extractDir))) {
paths.filter(Files::isRegularFile)
.forEach(path -> {
try {
long size = Files.size(path);
System.out.println(" " + path.getFileName() + ": " + size + " 字节");
} catch (IOException e) {
System.out.println(" " + path.getFileName() + ": 获取大小失败");
}
});
} catch (IOException e) {
System.out.println("验证解压结果失败: " + e.getMessage());
}
}
// GZIP压缩演示
public static void demonstrateGzipCompression() {
System.out.println("\n=== GZIP压缩演示 ===");
String sourceFile = "test1.txt";
String gzipFile = sourceFile + ".gz";
// GZIP压缩
try (FileInputStream fis = new FileInputStream(sourceFile);
GZIPOutputStream gzos = new GZIPOutputStream(
new FileOutputStream(gzipFile))) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
gzos.write(buffer, 0, bytesRead);
}
System.out.println("GZIP压缩完成: " + gzipFile);
} catch (IOException e) {
System.out.println("GZIP压缩失败: " + e.getMessage());
return;
}
// GZIP解压
String decompressedFile = "decompressed_" + sourceFile;
try (GZIPInputStream gzis = new GZIPInputStream(
new FileInputStream(gzipFile));
FileOutputStream fos = new FileOutputStream(decompressedFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = gzis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
System.out.println("GZIP解压完成: " + decompressedFile);
} catch (IOException e) {
System.out.println("GZIP解压失败: " + e.getMessage());
return;
}
// 比较文件大小
try {
long originalSize = Files.size(Paths.get(sourceFile));
long compressedSize = Files.size(Paths.get(gzipFile));
long decompressedSize = Files.size(Paths.get(decompressedFile));
System.out.println("\nGZIP压缩信息:");
System.out.println(" 原始文件: " + originalSize + " 字节");
System.out.println(" 压缩文件: " + compressedSize + " 字节");
System.out.println(" 解压文件: " + decompressedSize + " 字节");
System.out.println(" 压缩率: " + String.format("%.1f%%",
(1.0 - (double) compressedSize / originalSize) * 100));
System.out.println(" 数据完整性: " + (originalSize == decompressedSize ? "正确" : "错误"));
} catch (IOException e) {
System.out.println("获取GZIP文件信息失败: " + e.getMessage());
}
}
// 压缩性能测试
public static void demonstrateCompressionPerformance() {
System.out.println("\n=== 压缩性能测试 ===");
// 创建大文件用于测试
String testFile = "large_test.txt";
createLargeTestFile(testFile, 100000); // 10万行
try {
long originalSize = Files.size(Paths.get(testFile));
System.out.println("测试文件大小: " + formatBytes(originalSize));
// 测试不同压缩级别的ZIP
testZipCompressionLevels(testFile);
// 测试GZIP压缩
testGzipCompression(testFile);
} catch (IOException e) {
System.out.println("压缩性能测试失败: " + e.getMessage());
}
}
private static void createLargeTestFile(String fileName, int lines) {
try (PrintWriter pw = new PrintWriter(new FileWriter(fileName))) {
for (int i = 0; i < lines; i++) {
pw.println("这是第" + i + "行测试数据,包含一些重复的内容用于测试压缩效果。");
if (i % 10 == 0) {
pw.println("重复行:" + "重复内容 ".repeat(20));
}
}
} catch (IOException e) {
System.out.println("创建大文件失败: " + e.getMessage());
}
}
private static void testZipCompressionLevels(String sourceFile) {
System.out.println("\nZIP压缩级别测试:");
int[] levels = {Deflater.NO_COMPRESSION, Deflater.BEST_SPEED,
Deflater.DEFAULT_COMPRESSION, Deflater.BEST_COMPRESSION};
String[] levelNames = {"无压缩", "最快速度", "默认", "最佳压缩"};
for (int i = 0; i < levels.length; i++) {
String zipFile = "test_level_" + i + ".zip";
long startTime = System.currentTimeMillis();
try (ZipOutputStream zos = new ZipOutputStream(
new FileOutputStream(zipFile))) {
zos.setLevel(levels[i]);
ZipEntry entry = new ZipEntry(sourceFile);
zos.putNextEntry(entry);
Files.copy(Paths.get(sourceFile), zos);
zos.closeEntry();
} catch (IOException e) {
System.out.println(" " + levelNames[i] + ": 压缩失败");
continue;
}
long compressionTime = System.currentTimeMillis() - startTime;
try {
long originalSize = Files.size(Paths.get(sourceFile));
long compressedSize = Files.size(Paths.get(zipFile));
double ratio = (1.0 - (double) compressedSize / originalSize) * 100;
System.out.printf(" %s: %s -> %s (%.1f%%) 耗时: %dms%n",
levelNames[i], formatBytes(originalSize),
formatBytes(compressedSize), ratio, compressionTime);
} catch (IOException e) {
System.out.println(" " + levelNames[i] + ": 获取文件信息失败");
}
}
}
private static void testGzipCompression(String sourceFile) {
System.out.println("\nGZIP压缩测试:");
String gzipFile = sourceFile + ".perf.gz";
long startTime = System.currentTimeMillis();
try (FileInputStream fis = new FileInputStream(sourceFile);
GZIPOutputStream gzos = new GZIPOutputStream(
new FileOutputStream(gzipFile))) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
gzos.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
System.out.println(" GZIP压缩失败: " + e.getMessage());
return;
}
long compressionTime = System.currentTimeMillis() - startTime;
try {
long originalSize = Files.size(Paths.get(sourceFile));
long compressedSize = Files.size(Paths.get(gzipFile));
double ratio = (1.0 - (double) compressedSize / originalSize) * 100;
System.out.printf(" GZIP: %s -> %s (%.1f%%) 耗时: %dms%n",
formatBytes(originalSize), formatBytes(compressedSize),
ratio, compressionTime);
} catch (IOException e) {
System.out.println(" GZIP: 获取文件信息失败");
}
}
private static String formatBytes(long bytes) {
if (bytes < 1024) return bytes + " B";
if (bytes < 1024 * 1024) return String.format("%.1f KB", bytes / 1024.0);
if (bytes < 1024 * 1024 * 1024) return String.format("%.1f MB", bytes / (1024.0 * 1024));
return String.format("%.1f GB", bytes / (1024.0 * 1024 * 1024));
}
}
14.8 I/O最佳实践
14.8.1 性能优化和资源管理
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
import java.util.concurrent.*;
// I/O最佳实践演示
public class IOBestPracticesDemo {
public static void main(String[] args) {
// 资源管理最佳实践
demonstrateResourceManagement();
// 缓冲区优化
demonstrateBufferOptimization();
// 异步I/O
demonstrateAsyncIO();
// 错误处理
demonstrateErrorHandling();
// 性能监控
demonstratePerformanceMonitoring();
}
// 资源管理最佳实践
public static void demonstrateResourceManagement() {
System.out.println("=== 资源管理最佳实践 ===");
// 1. 使用try-with-resources(推荐)
System.out.println("1. try-with-resources模式:");
try (BufferedReader reader = Files.newBufferedReader(Paths.get("test.txt"));
BufferedWriter writer = Files.newBufferedWriter(Paths.get("output.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line.toUpperCase());
writer.newLine();
}
System.out.println(" 文件处理完成,资源自动关闭");
} catch (IOException e) {
System.out.println(" 文件处理失败: " + e.getMessage());
}
// 2. 自定义资源管理
System.out.println("\n2. 自定义资源管理:");
try (ManagedFileProcessor processor = new ManagedFileProcessor("test.txt")) {
processor.processFile();
System.out.println(" 自定义资源处理完成");
} catch (Exception e) {
System.out.println(" 自定义资源处理失败: " + e.getMessage());
}
// 3. 资源池管理
demonstrateResourcePool();
}
// 自定义资源管理类
static class ManagedFileProcessor implements AutoCloseable {
private final BufferedReader reader;
private final String fileName;
public ManagedFileProcessor(String fileName) throws IOException {
this.fileName = fileName;
this.reader = Files.newBufferedReader(Paths.get(fileName));
}
public void processFile() throws IOException {
String line;
int lineCount = 0;
while ((line = reader.readLine()) != null) {
lineCount++;
// 处理每一行
}
System.out.println(" 处理了 " + lineCount + " 行数据");
}
@Override
public void close() throws Exception {
if (reader != null) {
reader.close();
System.out.println(" 已关闭文件: " + fileName);
}
}
}
private static void demonstrateResourcePool() {
System.out.println("\n3. 资源池管理:");
// 简单的缓冲区池
BufferPool bufferPool = new BufferPool(5, 1024);
try {
ByteBuffer buffer1 = bufferPool.acquire();
ByteBuffer buffer2 = bufferPool.acquire();
System.out.println(" 获取缓冲区: " + buffer1.capacity() + " 字节");
System.out.println(" 获取缓冲区: " + buffer2.capacity() + " 字节");
// 使用缓冲区...
bufferPool.release(buffer1);
bufferPool.release(buffer2);
System.out.println(" 缓冲区已归还到池中");
} finally {
bufferPool.shutdown();
}
}
// 简单的缓冲区池实现
static class BufferPool {
private final BlockingQueue<ByteBuffer> pool;
private final int bufferSize;
public BufferPool(int poolSize, int bufferSize) {
this.bufferSize = bufferSize;
this.pool = new ArrayBlockingQueue<>(poolSize);
// 预创建缓冲区
for (int i = 0; i < poolSize; i++) {
pool.offer(ByteBuffer.allocateDirect(bufferSize));
}
}
public ByteBuffer acquire() throws InterruptedException {
ByteBuffer buffer = pool.poll(1, TimeUnit.SECONDS);
if (buffer == null) {
// 池中没有可用缓冲区,创建新的
buffer = ByteBuffer.allocateDirect(bufferSize);
}
buffer.clear();
return buffer;
}
public void release(ByteBuffer buffer) {
if (buffer != null) {
buffer.clear();
pool.offer(buffer);
}
}
public void shutdown() {
pool.clear();
}
}
// 缓冲区优化
public static void demonstrateBufferOptimization() {
System.out.println("\n=== 缓冲区优化 ===");
String testFile = "buffer_test.txt";
createTestFile(testFile, 50000); // 创建测试文件
// 测试不同缓冲区大小的性能
int[] bufferSizes = {512, 1024, 4096, 8192, 16384, 32768};
System.out.println("缓冲区大小性能测试:");
for (int bufferSize : bufferSizes) {
long startTime = System.nanoTime();
try (FileInputStream fis = new FileInputStream(testFile)) {
byte[] buffer = new byte[bufferSize];
long totalBytes = 0;
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
totalBytes += bytesRead;
}
long duration = System.nanoTime() - startTime;
System.out.printf(" 缓冲区 %6d 字节: %3d ms (读取 %d 字节)%n",
bufferSize, duration / 1000000, totalBytes);
} catch (IOException e) {
System.out.println(" 缓冲区 " + bufferSize + " 字节: 测试失败");
}
}
// 直接缓冲区 vs 堆缓冲区
compareDirectVsHeapBuffer(testFile);
}
private static void createTestFile(String fileName, int lines) {
try (PrintWriter pw = new PrintWriter(new FileWriter(fileName))) {
for (int i = 0; i < lines; i++) {
pw.println("这是第" + i + "行测试数据,用于缓冲区性能测试。");
}
} catch (IOException e) {
System.out.println("创建测试文件失败: " + e.getMessage());
}
}
private static void compareDirectVsHeapBuffer(String fileName) {
System.out.println("\n直接缓冲区 vs 堆缓冲区:");
int bufferSize = 8192;
// 堆缓冲区测试
long startTime = System.nanoTime();
try (FileChannel channel = FileChannel.open(Paths.get(fileName), StandardOpenOption.READ)) {
ByteBuffer heapBuffer = ByteBuffer.allocate(bufferSize);
long totalBytes = 0;
while (channel.read(heapBuffer) != -1) {
totalBytes += heapBuffer.position();
heapBuffer.clear();
}
long heapTime = System.nanoTime() - startTime;
System.out.printf(" 堆缓冲区: %d ms (读取 %d 字节)%n",
heapTime / 1000000, totalBytes);
} catch (IOException e) {
System.out.println(" 堆缓冲区测试失败: " + e.getMessage());
}
// 直接缓冲区测试
startTime = System.nanoTime();
try (FileChannel channel = FileChannel.open(Paths.get(fileName), StandardOpenOption.READ)) {
ByteBuffer directBuffer = ByteBuffer.allocateDirect(bufferSize);
long totalBytes = 0;
while (channel.read(directBuffer) != -1) {
totalBytes += directBuffer.position();
directBuffer.clear();
}
long directTime = System.nanoTime() - startTime;
System.out.printf(" 直接缓冲区: %d ms (读取 %d 字节)%n",
directTime / 1000000, totalBytes);
} catch (IOException e) {
System.out.println(" 直接缓冲区测试失败: " + e.getMessage());
}
}
// 异步I/O演示
public static void demonstrateAsyncIO() {
System.out.println("\n=== 异步I/O演示 ===");
// 使用CompletableFuture实现异步文件读取
CompletableFuture<String> asyncRead = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(100); // 模拟I/O延迟
return Files.readString(Paths.get("test.txt"));
} catch (Exception e) {
throw new RuntimeException("异步读取失败", e);
}
});
// 异步写入
CompletableFuture<Void> asyncWrite = CompletableFuture.runAsync(() -> {
try {
Thread.sleep(50); // 模拟I/O延迟
Files.writeString(Paths.get("async_output.txt"),
"异步写入的内容: " + System.currentTimeMillis());
} catch (Exception e) {
throw new RuntimeException("异步写入失败", e);
}
});
// 组合异步操作
CompletableFuture<String> combined = asyncRead
.thenCompose(content -> {
return CompletableFuture.supplyAsync(() -> {
return "处理后的内容: " + content.toUpperCase();
});
});
try {
// 等待所有异步操作完成
CompletableFuture.allOf(asyncWrite, combined).get(5, TimeUnit.SECONDS);
String result = combined.get();
System.out.println("异步操作完成");
System.out.println("处理结果长度: " + result.length());
} catch (Exception e) {
System.out.println("异步I/O操作失败: " + e.getMessage());
}
}
// 错误处理最佳实践
public static void demonstrateErrorHandling() {
System.out.println("\n=== 错误处理最佳实践 ===");
// 1. 具体的异常处理
System.out.println("1. 具体异常处理:");
try {
processFileWithSpecificExceptions("nonexistent.txt");
} catch (FileNotFoundException e) {
System.out.println(" 文件未找到: " + e.getMessage());
} catch (SecurityException e) {
System.out.println(" 安全异常: " + e.getMessage());
} catch (IOException e) {
System.out.println(" I/O异常: " + e.getMessage());
}
// 2. 重试机制
System.out.println("\n2. 重试机制:");
boolean success = retryOperation(() -> {
// 模拟可能失败的操作
if (Math.random() < 0.7) {
throw new IOException("模拟I/O错误");
}
return "操作成功";
}, 3, 1000);
System.out.println(" 重试操作结果: " + (success ? "成功" : "失败"));
// 3. 优雅降级
System.out.println("\n3. 优雅降级:");
String content = readFileWithFallback("important.txt", "默认内容");
System.out.println(" 读取内容: " + content);
}
private static void processFileWithSpecificExceptions(String fileName) throws IOException {
Path path = Paths.get(fileName);
// 检查文件是否存在
if (!Files.exists(path)) {
throw new FileNotFoundException("文件不存在: " + fileName);
}
// 检查读取权限
if (!Files.isReadable(path)) {
throw new SecurityException("没有读取权限: " + fileName);
}
// 读取文件
Files.readString(path);
}
private static boolean retryOperation(IOOperation operation, int maxRetries, long delayMs) {
for (int attempt = 1; attempt <= maxRetries; attempt++) {
try {
String result = operation.execute();
System.out.println(" 第" + attempt + "次尝试成功: " + result);
return true;
} catch (Exception e) {
System.out.println(" 第" + attempt + "次尝试失败: " + e.getMessage());
if (attempt < maxRetries) {
try {
Thread.sleep(delayMs);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
break;
}
}
}
}
return false;
}
@FunctionalInterface
interface IOOperation {
String execute() throws Exception;
}
private static String readFileWithFallback(String fileName, String fallbackContent) {
try {
return Files.readString(Paths.get(fileName));
} catch (IOException e) {
System.out.println(" 读取文件失败,使用默认内容: " + e.getMessage());
return fallbackContent;
}
}
// 性能监控
public static void demonstratePerformanceMonitoring() {
System.out.println("\n=== 性能监控 ===");
// I/O性能监控器
IOPerformanceMonitor monitor = new IOPerformanceMonitor();
String testFile = "performance_test.txt";
// 监控文件写入
monitor.startOperation("文件写入");
try (PrintWriter pw = new PrintWriter(new FileWriter(testFile))) {
for (int i = 0; i < 10000; i++) {
pw.println("测试行 " + i);
}
} catch (IOException e) {
System.out.println("写入失败: " + e.getMessage());
}
monitor.endOperation("文件写入");
// 监控文件读取
monitor.startOperation("文件读取");
try (BufferedReader br = new BufferedReader(new FileReader(testFile))) {
String line;
int lineCount = 0;
while ((line = br.readLine()) != null) {
lineCount++;
}
System.out.println("读取了 " + lineCount + " 行");
} catch (IOException e) {
System.out.println("读取失败: " + e.getMessage());
}
monitor.endOperation("文件读取");
// 显示性能统计
monitor.printStatistics();
}
// 简单的性能监控器
static class IOPerformanceMonitor {
private final Map<String, Long> startTimes = new HashMap<>();
private final Map<String, Long> durations = new HashMap<>();
private final Map<String, Integer> counts = new HashMap<>();
public void startOperation(String operationName) {
startTimes.put(operationName, System.nanoTime());
}
public void endOperation(String operationName) {
Long startTime = startTimes.remove(operationName);
if (startTime != null) {
long duration = System.nanoTime() - startTime;
durations.merge(operationName, duration, Long::sum);
counts.merge(operationName, 1, Integer::sum);
}
}
public void printStatistics() {
System.out.println("\n性能统计:");
for (String operation : durations.keySet()) {
long totalDuration = durations.get(operation);
int count = counts.get(operation);
long avgDuration = totalDuration / count;
System.out.printf(" %s: 总耗时=%dms, 次数=%d, 平均=%dms%n",
operation, totalDuration / 1000000, count, avgDuration / 1000000);
}
}
}
}
14.9 本章小结
14.9.1 I/O技术对比
技术类型 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
字节流 | 二进制数据、图片、音频 | 通用性强、效率高 | 不适合文本处理 |
字符流 | 文本文件、配置文件 | 编码处理、易读性 | 只适合文本数据 |
缓冲流 | 频繁读写操作 | 性能优化显著 | 内存占用增加 |
NIO | 大文件、高并发 | 内存映射、零拷贝 | 编程复杂度高 |
序列化 | 对象持久化、网络传输 | 对象完整性 | 版本兼容性问题 |
14.9.2 性能优化要点
选择合适的流类型
- 二进制数据使用字节流
- 文本数据使用字符流
- 频繁操作使用缓冲流
缓冲区大小优化
- 根据数据量选择合适的缓冲区大小
- 一般推荐8KB-32KB
- 大文件可以使用更大的缓冲区
资源管理
- 使用try-with-resources自动关闭资源
- 及时释放不再使用的流
- 考虑使用资源池管理重复使用的资源
NIO优化
- 大文件使用内存映射
- 批量操作使用Channel.transferTo()
- 高并发场景使用异步I/O
14.9.3 安全考虑
路径安全
- 验证文件路径,防止路径遍历攻击
- 限制文件访问范围
- 检查文件权限
资源限制
- 限制文件大小
- 控制并发I/O操作数量
- 设置超时时间
数据完整性
- 使用校验和验证数据完整性
- 实现重试机制
- 提供回滚功能
下一章预告
在下一章中,我们将学习Java数据库编程,包括: - JDBC基础操作 - 连接池管理 - 事务处理 - ORM框架使用 - 数据库性能优化
练习题
基础练习
文件复制工具
- 实现一个文件复制工具,支持进度显示
- 比较不同复制方法的性能
- 添加错误处理和重试机制
日志文件分析器
- 读取大型日志文件
- 统计不同级别的日志数量
- 提取错误信息并保存到单独文件
配置文件管理器
- 实现Properties文件的读写
- 支持配置项的增删改查
- 提供配置变更监听功能
进阶练习
文件压缩工具
- 实现目录的递归压缩
- 支持多种压缩格式
- 提供压缩进度和统计信息
对象序列化框架
- 实现自定义序列化协议
- 支持版本兼容性检查
- 提供序列化性能优化
高性能文件服务器
- 使用NIO实现文件服务器
- 支持断点续传
- 实现文件缓存机制
挑战练习
分布式文件系统客户端
- 实现文件的分片存储
- 支持数据冗余和恢复
- 提供一致性保证
实时日志监控系统
- 监控多个日志文件的变化
- 实时分析和告警
- 支持分布式部署
通过这些练习,你将深入掌握Java I/O编程的各个方面,为后续的数据库编程和网络编程打下坚实基础。
14.2 字节流操作
14.2.1 基础字节流
import java.io.*;
import java.util.*;
// 字节流操作演示
public class ByteStreamDemo {
public static void main(String[] args) {
// 文件字节流操作
demonstrateFileByteStream();
// 字节数组流操作
demonstrateByteArrayStream();
// 缓冲字节流操作
demonstrateBufferedByteStream();
// 数据流操作
demonstrateDataStream();
}
// 文件字节流操作
public static void demonstrateFileByteStream() {
System.out.println("=== 文件字节流操作 ===");
String fileName = "byte_test.txt";
String content = "Hello, 这是字节流测试内容!";
// 写入文件
try (FileOutputStream fos = new FileOutputStream(fileName)) {
byte[] bytes = content.getBytes("UTF-8");
fos.write(bytes);
System.out.println("写入文件成功,字节数: " + bytes.length);
} catch (IOException e) {
System.out.println("写入文件失败: " + e.getMessage());
}
// 读取文件
try (FileInputStream fis = new FileInputStream(fileName)) {
byte[] buffer = new byte[1024];
int bytesRead = fis.read(buffer);
if (bytesRead > 0) {
String readContent = new String(buffer, 0, bytesRead, "UTF-8");
System.out.println("读取内容: " + readContent);
System.out.println("读取字节数: " + bytesRead);
}
} catch (IOException e) {
System.out.println("读取文件失败: " + e.getMessage());
}
// 逐字节读取
try (FileInputStream fis = new FileInputStream(fileName)) {
System.out.println("\n逐字节读取:");
int byteValue;
int count = 0;
while ((byteValue = fis.read()) != -1 && count < 10) {
System.out.printf("字节[%d]: %d (字符: %c)%n", count, byteValue, (char)byteValue);
count++;
}
} catch (IOException e) {
System.out.println("逐字节读取失败: " + e.getMessage());
}
}
// 字节数组流操作
public static void demonstrateByteArrayStream() {
System.out.println("\n=== 字节数组流操作 ===");
// ByteArrayOutputStream写入数据
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
String data1 = "第一段数据";
String data2 = "第二段数据";
baos.write(data1.getBytes("UTF-8"));
baos.write('\n');
baos.write(data2.getBytes("UTF-8"));
byte[] result = baos.toByteArray();
System.out.println("写入的数据: " + new String(result, "UTF-8"));
System.out.println("总字节数: " + result.length);
} catch (IOException e) {
System.out.println("字节数组输出流操作失败: " + e.getMessage());
}
// ByteArrayInputStream读取数据
byte[] sourceData = "Hello ByteArrayInputStream!".getBytes();
try (ByteArrayInputStream bais = new ByteArrayInputStream(sourceData)) {
byte[] buffer = new byte[5];
int bytesRead;
System.out.println("\n分块读取字节数组:");
while ((bytesRead = bais.read(buffer)) != -1) {
String chunk = new String(buffer, 0, bytesRead);
System.out.println("读取块: " + chunk + " (" + bytesRead + " 字节)");
}
} catch (IOException e) {
System.out.println("字节数组输入流操作失败: " + e.getMessage());
}
}
// 缓冲字节流操作
public static void demonstrateBufferedByteStream() {
System.out.println("\n=== 缓冲字节流操作 ===");
String fileName = "buffered_test.txt";
// 性能对比:普通流 vs 缓冲流
byte[] testData = new byte[10000];
Arrays.fill(testData, (byte) 'A');
// 普通流写入
long startTime = System.currentTimeMillis();
try (FileOutputStream fos = new FileOutputStream(fileName + ".normal")) {
for (byte b : testData) {
fos.write(b);
}
} catch (IOException e) {
System.out.println("普通流写入失败: " + e.getMessage());
}
long normalTime = System.currentTimeMillis() - startTime;
// 缓冲流写入
startTime = System.currentTimeMillis();
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(fileName + ".buffered"))) {
for (byte b : testData) {
bos.write(b);
}
} catch (IOException e) {
System.out.println("缓冲流写入失败: " + e.getMessage());
}
long bufferedTime = System.currentTimeMillis() - startTime;
System.out.println("普通流写入时间: " + normalTime + "ms");
System.out.println("缓冲流写入时间: " + bufferedTime + "ms");
System.out.println("性能提升: " + (normalTime / (double) bufferedTime) + "倍");
// 缓冲流的缓冲区大小设置
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(fileName + ".buffered"), 8192)) {
byte[] buffer = new byte[1024];
int totalBytes = 0;
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
totalBytes += bytesRead;
}
System.out.println("\n缓冲流读取总字节数: " + totalBytes);
} catch (IOException e) {
System.out.println("缓冲流读取失败: " + e.getMessage());
}
}
// 数据流操作
public static void demonstrateDataStream() {
System.out.println("\n=== 数据流操作 ===");
String fileName = "data_test.dat";
// 写入各种数据类型
try (DataOutputStream dos = new DataOutputStream(
new FileOutputStream(fileName))) {
dos.writeBoolean(true);
dos.writeByte(127);
dos.writeShort(32767);
dos.writeInt(2147483647);
dos.writeLong(9223372036854775807L);
dos.writeFloat(3.14159f);
dos.writeDouble(2.718281828459045);
dos.writeUTF("Hello DataStream!");
System.out.println("数据写入完成");
} catch (IOException e) {
System.out.println("数据写入失败: " + e.getMessage());
}
// 读取各种数据类型
try (DataInputStream dis = new DataInputStream(
new FileInputStream(fileName))) {
boolean boolValue = dis.readBoolean();
byte byteValue = dis.readByte();
short shortValue = dis.readShort();
int intValue = dis.readInt();
long longValue = dis.readLong();
float floatValue = dis.readFloat();
double doubleValue = dis.readDouble();
String stringValue = dis.readUTF();
System.out.println("\n读取的数据:");
System.out.println(" boolean: " + boolValue);
System.out.println(" byte: " + byteValue);
System.out.println(" short: " + shortValue);
System.out.println(" int: " + intValue);
System.out.println(" long: " + longValue);
System.out.println(" float: " + floatValue);
System.out.println(" double: " + doubleValue);
System.out.println(" String: " + stringValue);
} catch (IOException e) {
System.out.println("数据读取失败: " + e.getMessage());
}
// 文件大小检查
File dataFile = new File(fileName);
if (dataFile.exists()) {
System.out.println("\n数据文件大小: " + dataFile.length() + " 字节");
}
}
}
14.3 字符流操作
14.3.1 基础字符流
import java.io.*;
import java.nio.charset.*;
import java.util.*;
// 字符流操作演示
public class CharacterStreamDemo {
public static void main(String[] args) {
// 文件字符流操作
demonstrateFileCharacterStream();
// 字符编码处理
demonstrateCharacterEncoding();
// 缓冲字符流操作
demonstrateBufferedCharacterStream();
// 字符串流操作
demonstrateStringStream();
// 打印流操作
demonstratePrintStream();
}
// 文件字符流操作
public static void demonstrateFileCharacterStream() {
System.out.println("=== 文件字符流操作 ===");
String fileName = "character_test.txt";
String content = "Hello World!\n你好,世界!\n这是字符流测试。";
// 写入文件
try (FileWriter fw = new FileWriter(fileName)) {
fw.write(content);
System.out.println("字符写入成功");
} catch (IOException e) {
System.out.println("字符写入失败: " + e.getMessage());
}
// 读取文件
try (FileReader fr = new FileReader(fileName)) {
char[] buffer = new char[1024];
int charsRead = fr.read(buffer);
if (charsRead > 0) {
String readContent = new String(buffer, 0, charsRead);
System.out.println("读取内容:");
System.out.println(readContent);
System.out.println("读取字符数: " + charsRead);
}
} catch (IOException e) {
System.out.println("字符读取失败: " + e.getMessage());
}
// 逐字符读取
try (FileReader fr = new FileReader(fileName)) {
System.out.println("\n逐字符读取前10个字符:");
int charValue;
int count = 0;
while ((charValue = fr.read()) != -1 && count < 10) {
char ch = (char) charValue;
System.out.printf("字符[%d]: %c (Unicode: %d)%n", count, ch, charValue);
count++;
}
} catch (IOException e) {
System.out.println("逐字符读取失败: " + e.getMessage());
}
}
// 字符编码处理
public static void demonstrateCharacterEncoding() {
System.out.println("\n=== 字符编码处理 ===");
String text = "Hello 世界 🌍";
String fileName = "encoding_test";
// 不同编码写入
String[] encodings = {"UTF-8", "UTF-16", "GBK", "ISO-8859-1"};
for (String encoding : encodings) {
try {
String file = fileName + "_" + encoding.replace("-", "") + ".txt";
// 使用指定编码写入
try (OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream(file), encoding)) {
osw.write(text);
}
// 读取并显示
try (InputStreamReader isr = new InputStreamReader(
new FileInputStream(file), encoding)) {
char[] buffer = new char[1024];
int charsRead = isr.read(buffer);
String readText = new String(buffer, 0, charsRead);
File f = new File(file);
System.out.printf("编码: %-10s 文件大小: %d 字节 内容: %s%n",
encoding, f.length(), readText);
}
} catch (IOException e) {
System.out.println(encoding + " 编码处理失败: " + e.getMessage());
} catch (UnsupportedEncodingException e) {
System.out.println("不支持的编码: " + encoding);
}
}
// 检测系统默认编码
System.out.println("\n系统信息:");
System.out.println("默认字符集: " + Charset.defaultCharset());
System.out.println("文件编码: " + System.getProperty("file.encoding"));
// 列出所有可用字符集
System.out.println("\n可用字符集 (前10个):");
Charset.availableCharsets().entrySet().stream()
.limit(10)
.forEach(entry -> System.out.println(" " + entry.getKey() + ": " + entry.getValue()));
}
// 缓冲字符流操作
public static void demonstrateBufferedCharacterStream() {
System.out.println("\n=== 缓冲字符流操作 ===");
String fileName = "buffered_char_test.txt";
// 使用BufferedWriter写入
try (BufferedWriter bw = new BufferedWriter(new FileWriter(fileName))) {
bw.write("第一行文本");
bw.newLine();
bw.write("第二行文本");
bw.newLine();
bw.write("第三行文本");
bw.flush(); // 强制刷新缓冲区
System.out.println("缓冲字符写入完成");
} catch (IOException e) {
System.out.println("缓冲字符写入失败: " + e.getMessage());
}
// 使用BufferedReader读取
try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
System.out.println("\n逐行读取:");
String line;
int lineNumber = 1;
while ((line = br.readLine()) != null) {
System.out.println("第" + lineNumber + "行: " + line);
lineNumber++;
}
} catch (IOException e) {
System.out.println("缓冲字符读取失败: " + e.getMessage());
}
// 性能测试:缓冲 vs 非缓冲
performanceTest();
}
private static void performanceTest() {
String fileName = "performance_test.txt";
int iterations = 10000;
// 非缓冲写入
long startTime = System.currentTimeMillis();
try (FileWriter fw = new FileWriter(fileName + ".normal")) {
for (int i = 0; i < iterations; i++) {
fw.write("Line " + i + "\n");
}
} catch (IOException e) {
System.out.println("非缓冲写入失败: " + e.getMessage());
}
long normalTime = System.currentTimeMillis() - startTime;
// 缓冲写入
startTime = System.currentTimeMillis();
try (BufferedWriter bw = new BufferedWriter(new FileWriter(fileName + ".buffered"))) {
for (int i = 0; i < iterations; i++) {
bw.write("Line " + i);
bw.newLine();
}
} catch (IOException e) {
System.out.println("缓冲写入失败: " + e.getMessage());
}
long bufferedTime = System.currentTimeMillis() - startTime;
System.out.println("\n性能测试结果 (" + iterations + " 次写入):");
System.out.println("非缓冲时间: " + normalTime + "ms");
System.out.println("缓冲时间: " + bufferedTime + "ms");
System.out.println("性能提升: " + (normalTime / (double) bufferedTime) + "倍");
}
// 字符串流操作
public static void demonstrateStringStream() {
System.out.println("\n=== 字符串流操作 ===");
// StringWriter - 将字符写入字符串
StringWriter sw = new StringWriter();
try {
sw.write("Hello ");
sw.write("StringWriter!");
sw.write("\n");
sw.write("这是第二行");
String result = sw.toString();
System.out.println("StringWriter结果:");
System.out.println(result);
// 获取内部缓冲区
StringBuffer buffer = sw.getBuffer();
System.out.println("缓冲区长度: " + buffer.length());
} catch (IOException e) {
System.out.println("StringWriter操作失败: " + e.getMessage());
}
// StringReader - 从字符串读取字符
String sourceText = "Hello StringReader!\n这是测试文本\n第三行";
try (StringReader sr = new StringReader(sourceText)) {
System.out.println("\nStringReader逐字符读取前20个字符:");
for (int i = 0; i < 20; i++) {
int ch = sr.read();
if (ch == -1) break;
char character = (char) ch;
if (character == '\n') {
System.out.print("\\n ");
} else {
System.out.print(character + " ");
}
}
System.out.println();
} catch (IOException e) {
System.out.println("StringReader操作失败: " + e.getMessage());
}
// 使用BufferedReader读取StringReader
try (BufferedReader br = new BufferedReader(new StringReader(sourceText))) {
System.out.println("\n使用BufferedReader逐行读取StringReader:");
String line;
int lineNum = 1;
while ((line = br.readLine()) != null) {
System.out.println("行" + lineNum + ": " + line);
lineNum++;
}
} catch (IOException e) {
System.out.println("BufferedReader读取StringReader失败: " + e.getMessage());
}
}
// 打印流操作
public static void demonstratePrintStream() {
System.out.println("\n=== 打印流操作 ===");
String fileName = "print_test.txt";
// PrintWriter操作
try (PrintWriter pw = new PrintWriter(new FileWriter(fileName))) {
// 各种打印方法
pw.println("这是一行文本");
pw.print("数字: ");
pw.println(42);
pw.printf("格式化输出: %s = %.2f%n", "π", Math.PI);
pw.println("布尔值: " + true);
// 打印对象
Date now = new Date();
pw.println("当前时间: " + now);
// 检查错误状态
if (pw.checkError()) {
System.out.println("PrintWriter发生错误");
} else {
System.out.println("PrintWriter写入成功");
}
} catch (IOException e) {
System.out.println("PrintWriter操作失败: " + e.getMessage());
}
// 读取并显示写入的内容
try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
System.out.println("\n读取PrintWriter写入的内容:");
String line;
while ((line = br.readLine()) != null) {
System.out.println(" " + line);
}
} catch (IOException e) {
System.out.println("读取PrintWriter文件失败: " + e.getMessage());
}
// PrintStream操作(重定向System.out)
try {
// 保存原始System.out
PrintStream originalOut = System.out;
// 重定向到文件
PrintStream fileOut = new PrintStream(new FileOutputStream("system_out.txt"));
System.setOut(fileOut);
// 这些输出会写入文件
System.out.println("这行输出被重定向到文件");
System.out.printf("格式化输出: %d + %d = %d%n", 1, 2, 3);
// 恢复原始输出
System.setOut(originalOut);
fileOut.close();
System.out.println("System.out重定向演示完成");
} catch (IOException e) {
System.out.println("PrintStream重定向失败: " + e.getMessage());
}
}
}
14.4 文件操作进阶
14.4.1 文件复制和移动
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.util.*;
import java.util.stream.*;
// 文件操作进阶演示
public class AdvancedFileOperationsDemo {
public static void main(String[] args) {
// 文件复制操作
demonstrateFileCopy();
// 目录操作
demonstrateDirectoryOperations();
// 文件属性操作
demonstrateFileAttributes();
// 文件监控
demonstrateFileWatcher();
// 临时文件操作
demonstrateTempFiles();
}
// 文件复制操作
public static void demonstrateFileCopy() {
System.out.println("=== 文件复制操作 ===");
// 创建测试文件
String sourceFile = "source.txt";
String content = "这是要复制的文件内容\n包含多行文本\n用于测试文件复制功能";
try (FileWriter fw = new FileWriter(sourceFile)) {
fw.write(content);
System.out.println("创建源文件: " + sourceFile);
} catch (IOException e) {
System.out.println("创建源文件失败: " + e.getMessage());
return;
}
// 方法1: 使用字节流复制
copyFileUsingByteStream(sourceFile, "copy1_byte.txt");
// 方法2: 使用字符流复制
copyFileUsingCharacterStream(sourceFile, "copy2_char.txt");
// 方法3: 使用缓冲流复制
copyFileUsingBufferedStream(sourceFile, "copy3_buffered.txt");
// 方法4: 使用NIO复制
copyFileUsingNIO(sourceFile, "copy4_nio.txt");
// 验证复制结果
verifyFileCopies(sourceFile, Arrays.asList(
"copy1_byte.txt", "copy2_char.txt", "copy3_buffered.txt", "copy4_nio.txt"
));
}
private static void copyFileUsingByteStream(String source, String target) {
long startTime = System.currentTimeMillis();
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(target)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
long duration = System.currentTimeMillis() - startTime;
System.out.println("字节流复制完成: " + target + " (耗时: " + duration + "ms)");
} catch (IOException e) {
System.out.println("字节流复制失败: " + e.getMessage());
}
}
private static void copyFileUsingCharacterStream(String source, String target) {
long startTime = System.currentTimeMillis();
try (FileReader fr = new FileReader(source);
FileWriter fw = new FileWriter(target)) {
char[] buffer = new char[1024];
int charsRead;
while ((charsRead = fr.read(buffer)) != -1) {
fw.write(buffer, 0, charsRead);
}
long duration = System.currentTimeMillis() - startTime;
System.out.println("字符流复制完成: " + target + " (耗时: " + duration + "ms)");
} catch (IOException e) {
System.out.println("字符流复制失败: " + e.getMessage());
}
}
private static void copyFileUsingBufferedStream(String source, String target) {
long startTime = System.currentTimeMillis();
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(target))) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
long duration = System.currentTimeMillis() - startTime;
System.out.println("缓冲流复制完成: " + target + " (耗时: " + duration + "ms)");
} catch (IOException e) {
System.out.println("缓冲流复制失败: " + e.getMessage());
}
}
private static void copyFileUsingNIO(String source, String target) {
long startTime = System.currentTimeMillis();
try {
Path sourcePath = Paths.get(source);
Path targetPath = Paths.get(target);
Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
long duration = System.currentTimeMillis() - startTime;
System.out.println("NIO复制完成: " + target + " (耗时: " + duration + "ms)");
} catch (IOException e) {
System.out.println("NIO复制失败: " + e.getMessage());
}
}
private static void verifyFileCopies(String original, List<String> copies) {
System.out.println("\n验证复制结果:");
try {
String originalContent = Files.readString(Paths.get(original));
long originalSize = Files.size(Paths.get(original));
System.out.println("原文件大小: " + originalSize + " 字节");
for (String copy : copies) {
try {
String copyContent = Files.readString(Paths.get(copy));
long copySize = Files.size(Paths.get(copy));
boolean contentMatch = originalContent.equals(copyContent);
boolean sizeMatch = originalSize == copySize;
System.out.printf(" %s: 大小匹配=%s, 内容匹配=%s%n",
copy, sizeMatch, contentMatch);
} catch (IOException e) {
System.out.println(" " + copy + ": 验证失败 - " + e.getMessage());
}
}
} catch (IOException e) {
System.out.println("读取原文件失败: " + e.getMessage());
}
}
// 目录操作
public static void demonstrateDirectoryOperations() {
System.out.println("\n=== 目录操作 ===");
String testDir = "test_directory";
Path testPath = Paths.get(testDir);
try {
// 创建目录
if (!Files.exists(testPath)) {
Files.createDirectory(testPath);
System.out.println("创建目录: " + testDir);
}
// 创建多级目录
Path multiLevelPath = Paths.get(testDir, "level1", "level2", "level3");
Files.createDirectories(multiLevelPath);
System.out.println("创建多级目录: " + multiLevelPath);
// 在目录中创建文件
for (int i = 1; i <= 3; i++) {
Path filePath = testPath.resolve("file" + i + ".txt");
Files.write(filePath, ("这是文件" + i + "的内容").getBytes());
}
// 列出目录内容
System.out.println("\n目录内容:");
try (Stream<Path> paths = Files.list(testPath)) {
paths.forEach(path -> {
try {
if (Files.isDirectory(path)) {
System.out.println(" [目录] " + path.getFileName());
} else {
long size = Files.size(path);
System.out.println(" [文件] " + path.getFileName() + " (" + size + " 字节)");
}
} catch (IOException e) {
System.out.println(" [错误] " + path.getFileName() + ": " + e.getMessage());
}
});
}
// 递归遍历目录
System.out.println("\n递归遍历目录:");
try (Stream<Path> paths = Files.walk(testPath)) {
paths.filter(Files::isRegularFile)
.forEach(path -> {
try {
long size = Files.size(path);
System.out.println(" " + path + " (" + size + " 字节)");
} catch (IOException e) {
System.out.println(" " + path + ": 获取大小失败");
}
});
}
// 查找文件
System.out.println("\n查找.txt文件:");
try (Stream<Path> paths = Files.find(testPath, 10,
(path, attrs) -> path.toString().endsWith(".txt"))) {
paths.forEach(path -> System.out.println(" 找到: " + path));
}
} catch (IOException e) {
System.out.println("目录操作失败: " + e.getMessage());
}
}
// 文件属性操作
public static void demonstrateFileAttributes() {
System.out.println("\n=== 文件属性操作 ===");
String fileName = "attributes_test.txt";
Path filePath = Paths.get(fileName);
try {
// 创建测试文件
Files.write(filePath, "测试文件属性".getBytes());
// 基本属性
BasicFileAttributes attrs = Files.readAttributes(filePath, BasicFileAttributes.class);
System.out.println("基本文件属性:");
System.out.println(" 文件大小: " + attrs.size() + " 字节");
System.out.println(" 创建时间: " + attrs.creationTime());
System.out.println(" 最后修改时间: " + attrs.lastModifiedTime());
System.out.println(" 最后访问时间: " + attrs.lastAccessTime());
System.out.println(" 是否为目录: " + attrs.isDirectory());
System.out.println(" 是否为常规文件: " + attrs.isRegularFile());
System.out.println(" 是否为符号链接: " + attrs.isSymbolicLink());
// 修改文件时间
FileTime newTime = FileTime.fromMillis(System.currentTimeMillis() - 86400000); // 一天前
Files.setLastModifiedTime(filePath, newTime);
System.out.println("\n修改文件时间后:");
System.out.println(" 新的最后修改时间: " + Files.getLastModifiedTime(filePath));
// 文件权限(在支持的系统上)
try {
Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(filePath);
System.out.println("\nPOSIX文件权限:");
permissions.forEach(perm -> System.out.println(" " + perm));
} catch (UnsupportedOperationException e) {
System.out.println("\n当前系统不支持POSIX文件权限");
}
// 文件存储信息
FileStore store = Files.getFileStore(filePath);
System.out.println("\n文件存储信息:");
System.out.println(" 存储名称: " + store.name());
System.out.println(" 文件系统类型: " + store.type());
System.out.println(" 总空间: " + formatBytes(store.getTotalSpace()));
System.out.println(" 可用空间: " + formatBytes(store.getUsableSpace()));
System.out.println(" 未分配空间: " + formatBytes(store.getUnallocatedSpace()));
} catch (IOException e) {
System.out.println("文件属性操作失败: " + e.getMessage());
}
}
private static String formatBytes(long bytes) {
if (bytes < 1024) return bytes + " B";
if (bytes < 1024 * 1024) return String.format("%.1f KB", bytes / 1024.0);
if (bytes < 1024 * 1024 * 1024) return String.format("%.1f MB", bytes / (1024.0 * 1024));
return String.format("%.1f GB", bytes / (1024.0 * 1024 * 1024));
}
// 文件监控
public static void demonstrateFileWatcher() {
System.out.println("\n=== 文件监控 ===");
Path watchDir = Paths.get("watch_test");
try {
// 创建监控目录
if (!Files.exists(watchDir)) {
Files.createDirectory(watchDir);
}
// 创建文件监控服务
WatchService watchService = FileSystems.getDefault().newWatchService();
// 注册监控事件
watchDir.register(watchService,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);
System.out.println("开始监控目录: " + watchDir);
System.out.println("将在5秒后创建、修改、删除文件进行测试...");
// 启动监控线程
Thread watchThread = new Thread(() -> {
try {
while (true) {
WatchKey key = watchService.take();
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
Path fileName = (Path) event.context();
System.out.println("检测到文件变化: " + kind + " - " + fileName);
}
if (!key.reset()) {
break;
}
}
} catch (InterruptedException e) {
System.out.println("文件监控被中断");
}
});
watchThread.setDaemon(true);
watchThread.start();
// 模拟文件操作
Thread.sleep(1000);
Path testFile = watchDir.resolve("test_watch.txt");
// 创建文件
Files.write(testFile, "初始内容".getBytes());
Thread.sleep(500);
// 修改文件
Files.write(testFile, "修改后的内容".getBytes());
Thread.sleep(500);
// 删除文件
Files.delete(testFile);
Thread.sleep(500);
System.out.println("文件监控演示完成");
} catch (IOException | InterruptedException e) {
System.out.println("文件监控失败: " + e.getMessage());
}
}
// 临时文件操作
public static void demonstrateTempFiles() {
System.out.println("\n=== 临时文件操作 ===");
try {
// 创建临时文件
Path tempFile = Files.createTempFile("demo", ".tmp");
System.out.println("创建临时文件: " + tempFile);
// 写入临时文件
String content = "这是临时文件的内容\n临时文件会在程序结束时自动删除";
Files.write(tempFile, content.getBytes());
// 读取临时文件
String readContent = Files.readString(tempFile);
System.out.println("临时文件内容:");
System.out.println(readContent);
// 设置删除钩子
tempFile.toFile().deleteOnExit();
System.out.println("已设置程序退出时删除临时文件");
// 创建临时目录
Path tempDir = Files.createTempDirectory("demo_dir");
System.out.println("创建临时目录: " + tempDir);
// 在临时目录中创建文件
Path tempFileInDir = tempDir.resolve("temp_file.txt");
Files.write(tempFileInDir, "临时目录中的文件".getBytes());
// 列出临时目录内容
try (Stream<Path> paths = Files.list(tempDir)) {
System.out.println("临时目录内容:");
paths.forEach(path -> System.out.println(" " + path.getFileName()));
}
// 获取系统临时目录
String systemTempDir = System.getProperty("java.io.tmpdir");
System.out.println("\n系统临时目录: " + systemTempDir);
// 清理临时目录
Files.deleteIfExists(tempFileInDir);
Files.deleteIfExists(tempDir);
System.out.println("清理临时目录完成");
} catch (IOException e) {
System.out.println("临时文件操作失败: " + e.getMessage());
}
}
}