9.1 I/O系统概述

9.1.1 I/O系统基础概念

Java的I/O系统是一个功能强大且复杂的体系,用于处理程序与外部世界的数据交换。理解I/O系统对于开发实际应用程序至关重要。

import java.io.*;
import java.nio.file.*;
import java.util.*;

/**
 * I/O系统概述演示
 */
public class IOSystemOverview {
    public static void main(String[] args) {
        System.out.println("=== Java I/O系统概述 ===");
        
        demonstrateIOConcepts();
        demonstrateStreamTypes();
        demonstrateIOHierarchy();
        demonstrateCommonUseCases();
    }
    
    public static void demonstrateIOConcepts() {
        System.out.println("\n--- I/O基础概念 ---");
        
        System.out.println("\n1. I/O的基本概念:");
        System.out.println("- Input(输入): 从外部数据源读取数据到程序中");
        System.out.println("- Output(输出): 从程序中写入数据到外部目标");
        System.out.println("- Stream(流): 数据传输的抽象概念,数据的有序序列");
        System.out.println("- Buffer(缓冲区): 临时存储数据的内存区域");
        
        System.out.println("\n2. I/O的分类:");
        System.out.println("按数据类型分类:");
        System.out.println("  - 字节流(Byte Stream): 处理8位字节数据");
        System.out.println("  - 字符流(Character Stream): 处理16位Unicode字符");
        
        System.out.println("\n按数据流向分类:");
        System.out.println("  - 输入流(Input Stream): 从数据源读取数据");
        System.out.println("  - 输出流(Output Stream): 向目标写入数据");
        
        System.out.println("\n按功能分类:");
        System.out.println("  - 节点流(Node Stream): 直接连接数据源/目标");
        System.out.println("  - 处理流(Processing Stream): 对其他流进行包装,提供额外功能");
        
        System.out.println("\n3. I/O的发展历程:");
        System.out.println("- Java 1.0: 基础I/O(java.io包)");
        System.out.println("- Java 1.4: NIO(New I/O,java.nio包)");
        System.out.println("- Java 7: NIO.2(改进的文件系统API)");
        System.out.println("- Java 8+: Stream API与I/O的结合");
    }
    
    public static void demonstrateStreamTypes() {
        System.out.println("\n--- 流的类型演示 ---");
        
        // 1. 字节流示例
        System.out.println("\n1. 字节流示例:");
        try {
            // 创建临时文件
            File tempFile = File.createTempFile("byte_example", ".dat");
            tempFile.deleteOnExit();
            
            // 写入字节数据
            try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                byte[] data = {65, 66, 67, 68, 69}; // ASCII码:A, B, C, D, E
                fos.write(data);
                System.out.println("写入字节数据: " + Arrays.toString(data));
            }
            
            // 读取字节数据
            try (FileInputStream fis = new FileInputStream(tempFile)) {
                byte[] buffer = new byte[10];
                int bytesRead = fis.read(buffer);
                System.out.println("读取字节数据: " + Arrays.toString(Arrays.copyOf(buffer, bytesRead)));
                System.out.println("转换为字符: " + new String(buffer, 0, bytesRead));
            }
            
        } catch (IOException e) {
            System.err.println("字节流操作失败: " + e.getMessage());
        }
        
        // 2. 字符流示例
        System.out.println("\n2. 字符流示例:");
        try {
            // 创建临时文件
            File tempFile = File.createTempFile("char_example", ".txt");
            tempFile.deleteOnExit();
            
            // 写入字符数据
            try (FileWriter fw = new FileWriter(tempFile)) {
                String text = "Hello, 世界! 🌍";
                fw.write(text);
                System.out.println("写入字符数据: " + text);
            }
            
            // 读取字符数据
            try (FileReader fr = new FileReader(tempFile)) {
                char[] buffer = new char[20];
                int charsRead = fr.read(buffer);
                String result = new String(buffer, 0, charsRead);
                System.out.println("读取字符数据: " + result);
            }
            
        } catch (IOException e) {
            System.err.println("字符流操作失败: " + e.getMessage());
        }
        
        // 3. 缓冲流示例
        System.out.println("\n3. 缓冲流示例:");
        try {
            File tempFile = File.createTempFile("buffer_example", ".txt");
            tempFile.deleteOnExit();
            
            // 使用缓冲流写入
            try (BufferedWriter bw = new BufferedWriter(new FileWriter(tempFile))) {
                for (int i = 1; i <= 5; i++) {
                    bw.write("Line " + i);
                    bw.newLine();
                }
                System.out.println("使用缓冲流写入5行数据");
            }
            
            // 使用缓冲流读取
            try (BufferedReader br = new BufferedReader(new FileReader(tempFile))) {
                String line;
                System.out.println("使用缓冲流读取数据:");
                while ((line = br.readLine()) != null) {
                    System.out.println("  " + line);
                }
            }
            
        } catch (IOException e) {
            System.err.println("缓冲流操作失败: " + e.getMessage());
        }
    }
    
    public static void demonstrateIOHierarchy() {
        System.out.println("\n--- I/O类层次结构 ---");
        
        System.out.println("\n1. 字节流层次结构:");
        System.out.println("InputStream (抽象基类)");
        System.out.println("├── FileInputStream (文件输入流)");
        System.out.println("├── ByteArrayInputStream (字节数组输入流)");
        System.out.println("├── BufferedInputStream (缓冲输入流)");
        System.out.println("├── DataInputStream (数据输入流)");
        System.out.println("└── ObjectInputStream (对象输入流)");
        
        System.out.println("\nOutputStream (抽象基类)");
        System.out.println("├── FileOutputStream (文件输出流)");
        System.out.println("├── ByteArrayOutputStream (字节数组输出流)");
        System.out.println("├── BufferedOutputStream (缓冲输出流)");
        System.out.println("├── DataOutputStream (数据输出流)");
        System.out.println("└── ObjectOutputStream (对象输出流)");
        
        System.out.println("\n2. 字符流层次结构:");
        System.out.println("Reader (抽象基类)");
        System.out.println("├── FileReader (文件读取器)");
        System.out.println("├── StringReader (字符串读取器)");
        System.out.println("├── BufferedReader (缓冲读取器)");
        System.out.println("├── InputStreamReader (输入流读取器)");
        System.out.println("└── CharArrayReader (字符数组读取器)");
        
        System.out.println("\nWriter (抽象基类)");
        System.out.println("├── FileWriter (文件写入器)");
        System.out.println("├── StringWriter (字符串写入器)");
        System.out.println("├── BufferedWriter (缓冲写入器)");
        System.out.println("├── OutputStreamWriter (输出流写入器)");
        System.out.println("└── CharArrayWriter (字符数组写入器)");
        
        System.out.println("\n3. 特殊用途类:");
        System.out.println("- RandomAccessFile: 随机访问文件");
        System.out.println("- File: 文件和目录的抽象表示");
        System.out.println("- Path: NIO.2中的路径表示");
        System.out.println("- Files: NIO.2中的文件操作工具类");
    }
    
    public static void demonstrateCommonUseCases() {
        System.out.println("\n--- 常见I/O使用场景 ---");
        
        System.out.println("\n1. 文件操作:");
        System.out.println("- 读取配置文件");
        System.out.println("- 写入日志文件");
        System.out.println("- 处理CSV/JSON数据文件");
        System.out.println("- 文件复制和移动");
        
        System.out.println("\n2. 网络通信:");
        System.out.println("- Socket通信");
        System.out.println("- HTTP请求和响应");
        System.out.println("- 文件上传和下载");
        
        System.out.println("\n3. 数据序列化:");
        System.out.println("- 对象持久化");
        System.out.println("- 缓存数据存储");
        System.out.println("- 网络数据传输");
        
        System.out.println("\n4. 内存操作:");
        System.out.println("- 字节数组操作");
        System.out.println("- 字符串构建");
        System.out.println("- 临时数据处理");
        
        System.out.println("\n5. 系统交互:");
        System.out.println("- 控制台输入输出");
        System.out.println("- 系统属性读取");
        System.out.println("- 环境变量访问");
        
        // 实际示例:简单的文件操作
        demonstrateSimpleFileOperations();
    }
    
    private static void demonstrateSimpleFileOperations() {
        System.out.println("\n--- 简单文件操作示例 ---");
        
        try {
            // 1. 创建临时目录和文件
            Path tempDir = Files.createTempDirectory("io_demo");
            Path tempFile = tempDir.resolve("example.txt");
            
            System.out.println("创建临时目录: " + tempDir);
            System.out.println("创建临时文件: " + tempFile);
            
            // 2. 写入文件
            List<String> lines = Arrays.asList(
                "这是第一行",
                "这是第二行",
                "这是第三行,包含中文和数字123"
            );
            Files.write(tempFile, lines);
            System.out.println("\n写入文件内容:");
            lines.forEach(line -> System.out.println("  " + line));
            
            // 3. 读取文件
            List<String> readLines = Files.readAllLines(tempFile);
            System.out.println("\n读取文件内容:");
            readLines.forEach(line -> System.out.println("  " + line));
            
            // 4. 文件信息
            System.out.println("\n文件信息:");
            System.out.println("文件大小: " + Files.size(tempFile) + " 字节");
            System.out.println("是否存在: " + Files.exists(tempFile));
            System.out.println("是否可读: " + Files.isReadable(tempFile));
            System.out.println("是否可写: " + Files.isWritable(tempFile));
            
            // 5. 清理临时文件
            Files.deleteIfExists(tempFile);
            Files.deleteIfExists(tempDir);
            System.out.println("\n清理临时文件完成");
            
        } catch (IOException e) {
            System.err.println("文件操作失败: " + e.getMessage());
        }
    }
}

9.1.2 I/O性能考虑

import java.io.*;
import java.nio.file.*;
import java.util.concurrent.ThreadLocalRandom;

/**
 * I/O性能演示
 */
public class IOPerformanceDemo {
    public static void main(String[] args) {
        System.out.println("=== I/O性能演示 ===");
        
        demonstrateBufferImportance();
        demonstrateStreamVsNIO();
        demonstrateBestPractices();
    }
    
    public static void demonstrateBufferImportance() {
        System.out.println("\n--- 缓冲区重要性演示 ---");
        
        try {
            // 准备测试数据
            byte[] testData = new byte[1024 * 1024]; // 1MB数据
            ThreadLocalRandom.current().nextBytes(testData);
            
            File tempFile = File.createTempFile("performance_test", ".dat");
            tempFile.deleteOnExit();
            
            // 1. 无缓冲写入
            long startTime = System.nanoTime();
            try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                for (byte b : testData) {
                    fos.write(b); // 逐字节写入
                }
            }
            long unbufferedWriteTime = System.nanoTime() - startTime;
            
            // 2. 有缓冲写入
            startTime = System.nanoTime();
            try (BufferedOutputStream bos = new BufferedOutputStream(
                    new FileOutputStream(tempFile))) {
                for (byte b : testData) {
                    bos.write(b);
                }
            }
            long bufferedWriteTime = System.nanoTime() - startTime;
            
            // 3. 批量写入
            startTime = System.nanoTime();
            try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                fos.write(testData); // 一次性写入
            }
            long bulkWriteTime = System.nanoTime() - startTime;
            
            System.out.println("写入1MB数据的性能对比:");
            System.out.println("无缓冲逐字节写入: " + unbufferedWriteTime / 1_000_000 + "ms");
            System.out.println("有缓冲逐字节写入: " + bufferedWriteTime / 1_000_000 + "ms");
            System.out.println("批量写入: " + bulkWriteTime / 1_000_000 + "ms");
            
            System.out.println("\n性能提升:");
            System.out.println("缓冲流比无缓冲快: " + 
                (unbufferedWriteTime / (double) bufferedWriteTime) + "倍");
            System.out.println("批量写入比无缓冲快: " + 
                (unbufferedWriteTime / (double) bulkWriteTime) + "倍");
            
        } catch (IOException e) {
            System.err.println("性能测试失败: " + e.getMessage());
        }
    }
    
    public static void demonstrateStreamVsNIO() {
        System.out.println("\n--- 传统I/O vs NIO性能对比 ---");
        
        try {
            // 准备测试文件
            Path sourceFile = Files.createTempFile("source", ".dat");
            Path targetFile1 = Files.createTempFile("target1", ".dat");
            Path targetFile2 = Files.createTempFile("target2", ".dat");
            
            // 创建10MB测试文件
            byte[] data = new byte[10 * 1024 * 1024];
            ThreadLocalRandom.current().nextBytes(data);
            Files.write(sourceFile, data);
            
            System.out.println("测试文件大小: " + Files.size(sourceFile) / (1024 * 1024) + "MB");
            
            // 1. 传统I/O复制
            long startTime = System.nanoTime();
            try (FileInputStream fis = new FileInputStream(sourceFile.toFile());
                 FileOutputStream fos = new FileOutputStream(targetFile1.toFile())) {
                
                byte[] buffer = new byte[8192];
                int bytesRead;
                while ((bytesRead = fis.read(buffer)) != -1) {
                    fos.write(buffer, 0, bytesRead);
                }
            }
            long traditionalIOTime = System.nanoTime() - startTime;
            
            // 2. NIO复制
            startTime = System.nanoTime();
            Files.copy(sourceFile, targetFile2, StandardCopyOption.REPLACE_EXISTING);
            long nioTime = System.nanoTime() - startTime;
            
            System.out.println("\n文件复制性能对比:");
            System.out.println("传统I/O: " + traditionalIOTime / 1_000_000 + "ms");
            System.out.println("NIO: " + nioTime / 1_000_000 + "ms");
            
            if (nioTime > 0) {
                System.out.println("NIO比传统I/O快: " + 
                    (traditionalIOTime / (double) nioTime) + "倍");
            }
            
            // 清理文件
            Files.deleteIfExists(sourceFile);
            Files.deleteIfExists(targetFile1);
            Files.deleteIfExists(targetFile2);
            
        } catch (IOException e) {
            System.err.println("NIO性能测试失败: " + e.getMessage());
        }
    }
    
    public static void demonstrateBestPractices() {
        System.out.println("\n--- I/O最佳实践 ---");
        
        System.out.println("\n1. 资源管理:");
        System.out.println("✓ 使用try-with-resources自动关闭流");
        System.out.println("✓ 在finally块中手动关闭(Java 7之前)");
        System.out.println("✗ 忘记关闭流会导致资源泄漏");
        
        System.out.println("\n2. 缓冲策略:");
        System.out.println("✓ 对频繁的小量I/O操作使用缓冲流");
        System.out.println("✓ 根据数据大小选择合适的缓冲区大小");
        System.out.println("✓ 大文件操作考虑使用NIO");
        
        System.out.println("\n3. 异常处理:");
        System.out.println("✓ 捕获并处理IOException");
        System.out.println("✓ 提供有意义的错误信息");
        System.out.println("✓ 考虑重试机制(网络I/O)");
        
        System.out.println("\n4. 编码处理:");
        System.out.println("✓ 明确指定字符编码");
        System.out.println("✓ 使用UTF-8作为默认编码");
        System.out.println("✗ 依赖平台默认编码");
        
        System.out.println("\n5. 性能优化:");
        System.out.println("✓ 批量操作优于逐个操作");
        System.out.println("✓ 异步I/O用于高并发场景");
        System.out.println("✓ 内存映射文件用于大文件随机访问");
        
        // 演示正确的资源管理
        demonstrateResourceManagement();
    }
    
    private static void demonstrateResourceManagement() {
        System.out.println("\n--- 资源管理示例 ---");
        
        try {
            Path tempFile = Files.createTempFile("resource_demo", ".txt");
            
            // 正确的资源管理方式
            System.out.println("\n✓ 正确的资源管理(try-with-resources):");
            try (BufferedWriter writer = Files.newBufferedWriter(tempFile);
                 BufferedReader reader = Files.newBufferedReader(tempFile)) {
                
                writer.write("Hello, World!");
                writer.flush();
                
                // 注意:这里为了演示,实际上需要重新打开文件来读取
                System.out.println("资源会自动关闭");
                
            } // 资源在这里自动关闭
            
            System.out.println("\n✓ 手动资源管理(Java 7之前的方式):");
            FileWriter writer = null;
            try {
                writer = new FileWriter(tempFile.toFile());
                writer.write("Manual resource management");
                System.out.println("手动管理资源");
            } finally {
                if (writer != null) {
                    try {
                        writer.close();
                        System.out.println("手动关闭资源");
                    } catch (IOException e) {
                        System.err.println("关闭资源时出错: " + e.getMessage());
                    }
                }
            }
            
            Files.deleteIfExists(tempFile);
            
        } catch (IOException e) {
            System.err.println("资源管理演示失败: " + e.getMessage());
        }
    }
}

9.2 文件操作

9.2.1 File类详解

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.time.*;
import java.util.*;

/**
 * File类详细演示
 */
public class FileClassDemo {
    public static void main(String[] args) {
        System.out.println("=== File类详细演示 ===");
        
        demonstrateFileBasics();
        demonstrateFileOperations();
        demonstrateDirectoryOperations();
        demonstrateFileProperties();
        demonstrateFileFiltering();
    }
    
    public static void demonstrateFileBasics() {
        System.out.println("\n--- File类基础 ---");
        
        // 1. 创建File对象的不同方式
        System.out.println("\n1. 创建File对象:");
        
        // 绝对路径
        File absoluteFile = new File("C:\\temp\\example.txt");
        System.out.println("绝对路径: " + absoluteFile.getAbsolutePath());
        
        // 相对路径
        File relativeFile = new File("example.txt");
        System.out.println("相对路径: " + relativeFile.getPath());
        System.out.println("转换为绝对路径: " + relativeFile.getAbsolutePath());
        
        // 父目录和文件名
        File parentDirFile = new File("temp", "example.txt");
        System.out.println("父目录+文件名: " + parentDirFile.getPath());
        
        // 父File对象和文件名
        File parentFile = new File("temp");
        File childFile = new File(parentFile, "example.txt");
        System.out.println("父File对象+文件名: " + childFile.getPath());
        
        // 2. 路径分隔符
        System.out.println("\n2. 路径分隔符:");
        System.out.println("文件分隔符: '" + File.separator + "'");
        System.out.println("路径分隔符: '" + File.pathSeparator + "'");
        
        // 跨平台路径构建
        String crossPlatformPath = "temp" + File.separator + "subdir" + File.separator + "file.txt";
        System.out.println("跨平台路径: " + crossPlatformPath);
        
        // 3. 当前工作目录
        System.out.println("\n3. 当前工作目录:");
        System.out.println("当前目录: " + System.getProperty("user.dir"));
        System.out.println("用户主目录: " + System.getProperty("user.home"));
        System.out.println("临时目录: " + System.getProperty("java.io.tmpdir"));
    }
    
    public static void demonstrateFileOperations() {
        System.out.println("\n--- 文件操作 ---");
        
        try {
            // 创建临时目录用于演示
            File tempDir = new File(System.getProperty("java.io.tmpdir"), "file_demo");
            if (!tempDir.exists()) {
                tempDir.mkdirs();
            }
            
            File testFile = new File(tempDir, "test.txt");
            
            // 1. 文件创建
            System.out.println("\n1. 文件创建:");
            if (testFile.createNewFile()) {
                System.out.println("文件创建成功: " + testFile.getAbsolutePath());
            } else {
                System.out.println("文件已存在: " + testFile.getAbsolutePath());
            }
            
            // 2. 文件写入
            System.out.println("\n2. 文件写入:");
            try (FileWriter writer = new FileWriter(testFile)) {
                writer.write("Hello, File Operations!\n");
                writer.write("这是第二行\n");
                writer.write("Current time: " + new Date());
                System.out.println("文件写入完成");
            }
            
            // 3. 文件读取
            System.out.println("\n3. 文件读取:");
            try (BufferedReader reader = new BufferedReader(new FileReader(testFile))) {
                String line;
                int lineNumber = 1;
                while ((line = reader.readLine()) != null) {
                    System.out.println("第" + lineNumber + "行: " + line);
                    lineNumber++;
                }
            }
            
            // 4. 文件复制
            System.out.println("\n4. 文件复制:");
            File copyFile = new File(tempDir, "test_copy.txt");
            copyFileUsingStreams(testFile, copyFile);
            System.out.println("文件复制完成: " + copyFile.getAbsolutePath());
            
            // 5. 文件重命名
            System.out.println("\n5. 文件重命名:");
            File renamedFile = new File(tempDir, "test_renamed.txt");
            if (copyFile.renameTo(renamedFile)) {
                System.out.println("文件重命名成功: " + renamedFile.getName());
            } else {
                System.out.println("文件重命名失败");
            }
            
            // 6. 文件删除
            System.out.println("\n6. 文件删除:");
            if (testFile.delete()) {
                System.out.println("原文件删除成功");
            }
            if (renamedFile.delete()) {
                System.out.println("重命名文件删除成功");
            }
            
            // 清理临时目录
            tempDir.delete();
            
        } catch (IOException e) {
            System.err.println("文件操作失败: " + e.getMessage());
        }
    }
    
    private static void copyFileUsingStreams(File source, File target) throws IOException {
        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);
            }
        }
    }
    
    public static void demonstrateDirectoryOperations() {
        System.out.println("\n--- 目录操作 ---");
        
        try {
            // 创建测试目录结构
            File baseDir = new File(System.getProperty("java.io.tmpdir"), "dir_demo");
            File subDir1 = new File(baseDir, "subdir1");
            File subDir2 = new File(baseDir, "subdir2");
            File nestedDir = new File(subDir1, "nested");
            
            // 1. 目录创建
            System.out.println("\n1. 目录创建:");
            if (baseDir.mkdir()) {
                System.out.println("创建基础目录: " + baseDir.getName());
            }
            
            if (subDir1.mkdir()) {
                System.out.println("创建子目录1: " + subDir1.getName());
            }
            
            if (subDir2.mkdir()) {
                System.out.println("创建子目录2: " + subDir2.getName());
            }
            
            if (nestedDir.mkdirs()) { // 创建多级目录
                System.out.println("创建嵌套目录: " + nestedDir.getPath());
            }
            
            // 2. 在目录中创建文件
            System.out.println("\n2. 在目录中创建文件:");
            File file1 = new File(subDir1, "file1.txt");
            File file2 = new File(subDir2, "file2.txt");
            File file3 = new File(nestedDir, "file3.txt");
            
            createFileWithContent(file1, "Content of file1");
            createFileWithContent(file2, "Content of file2");
            createFileWithContent(file3, "Content of file3");
            
            // 3. 目录遍历
            System.out.println("\n3. 目录遍历:");
            System.out.println("基础目录内容:");
            listDirectoryContents(baseDir, 0);
            
            // 4. 目录信息
            System.out.println("\n4. 目录信息:");
            System.out.println("基础目录路径: " + baseDir.getAbsolutePath());
            System.out.println("是否为目录: " + baseDir.isDirectory());
            System.out.println("是否为文件: " + baseDir.isFile());
            System.out.println("是否可读: " + baseDir.canRead());
            System.out.println("是否可写: " + baseDir.canWrite());
            
            // 5. 递归删除目录
            System.out.println("\n5. 递归删除目录:");
            deleteDirectoryRecursively(baseDir);
            System.out.println("目录删除完成");
            
        } catch (IOException e) {
            System.err.println("目录操作失败: " + e.getMessage());
        }
    }
    
    private static void createFileWithContent(File file, String content) throws IOException {
        try (FileWriter writer = new FileWriter(file)) {
            writer.write(content);
        }
        System.out.println("创建文件: " + file.getName());
    }
    
    private static void listDirectoryContents(File dir, int level) {
        if (!dir.isDirectory()) {
            return;
        }
        
        String indent = "  ".repeat(level);
        File[] files = dir.listFiles();
        
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    System.out.println(indent + "[DIR] " + file.getName());
                    listDirectoryContents(file, level + 1);
                } else {
                    System.out.println(indent + "[FILE] " + file.getName() + 
                        " (" + file.length() + " bytes)");
                }
            }
        }
    }
    
    private static void deleteDirectoryRecursively(File dir) {
        if (dir.isDirectory()) {
            File[] files = dir.listFiles();
            if (files != null) {
                for (File file : files) {
                    deleteDirectoryRecursively(file);
                }
            }
        }
        dir.delete();
    }
    
    public static void demonstrateFileProperties() {
        System.out.println("\n--- 文件属性 ---");
        
        try {
            // 创建测试文件
            File testFile = File.createTempFile("properties_test", ".txt");
            testFile.deleteOnExit();
            
            // 写入一些内容
            try (FileWriter writer = new FileWriter(testFile)) {
                writer.write("This is a test file for properties demonstration.");
            }
            
            // 1. 基本属性
            System.out.println("\n1. 基本属性:");
            System.out.println("文件名: " + testFile.getName());
            System.out.println("父目录: " + testFile.getParent());
            System.out.println("绝对路径: " + testFile.getAbsolutePath());
            System.out.println("规范路径: " + testFile.getCanonicalPath());
            
            // 2. 文件状态
            System.out.println("\n2. 文件状态:");
            System.out.println("是否存在: " + testFile.exists());
            System.out.println("是否为文件: " + testFile.isFile());
            System.out.println("是否为目录: " + testFile.isDirectory());
            System.out.println("是否为隐藏文件: " + testFile.isHidden());
            System.out.println("是否为绝对路径: " + testFile.isAbsolute());
            
            // 3. 权限
            System.out.println("\n3. 权限:");
            System.out.println("是否可读: " + testFile.canRead());
            System.out.println("是否可写: " + testFile.canWrite());
            System.out.println("是否可执行: " + testFile.canExecute());
            
            // 4. 大小和时间
            System.out.println("\n4. 大小和时间:");
            System.out.println("文件大小: " + testFile.length() + " 字节");
            System.out.println("最后修改时间: " + new Date(testFile.lastModified()));
            
            // 5. 修改属性
            System.out.println("\n5. 修改属性:");
            long newTime = System.currentTimeMillis() - 24 * 60 * 60 * 1000; // 昨天
            if (testFile.setLastModified(newTime)) {
                System.out.println("修改时间设置成功: " + new Date(testFile.lastModified()));
            }
            
            if (testFile.setReadOnly()) {
                System.out.println("设置为只读成功");
                System.out.println("现在是否可写: " + testFile.canWrite());
            }
            
            // 恢复可写权限(在某些系统上可能不起作用)
            testFile.setWritable(true);
            
        } catch (IOException e) {
            System.err.println("文件属性操作失败: " + e.getMessage());
        }
    }
    
    public static void demonstrateFileFiltering() {
        System.out.println("\n--- 文件过滤 ---");
        
        try {
            // 创建测试目录和文件
            File testDir = new File(System.getProperty("java.io.tmpdir"), "filter_demo");
            testDir.mkdirs();
            
            // 创建不同类型的文件
            createFileWithContent(new File(testDir, "document.txt"), "Text document");
            createFileWithContent(new File(testDir, "data.csv"), "CSV data");
            createFileWithContent(new File(testDir, "config.properties"), "Configuration");
            createFileWithContent(new File(testDir, "script.bat"), "Batch script");
            createFileWithContent(new File(testDir, "readme.md"), "Markdown file");
            
            File subDir = new File(testDir, "subdirectory");
            subDir.mkdir();
            
            System.out.println("\n创建的测试文件:");
            File[] allFiles = testDir.listFiles();
            if (allFiles != null) {
                for (File file : allFiles) {
                    System.out.println("  " + file.getName() + 
                        (file.isDirectory() ? " [目录]" : " [文件]"));
                }
            }
            
            // 1. 使用FilenameFilter
            System.out.println("\n1. 使用FilenameFilter过滤:");
            
            // 过滤.txt文件
            FilenameFilter txtFilter = (dir, name) -> name.toLowerCase().endsWith(".txt");
            File[] txtFiles = testDir.listFiles(txtFilter);
            System.out.println("TXT文件:");
            if (txtFiles != null) {
                for (File file : txtFiles) {
                    System.out.println("  " + file.getName());
                }
            }
            
            // 过滤以特定字符开头的文件
            FilenameFilter startsWithFilter = (dir, name) -> name.toLowerCase().startsWith("d");
            File[] startsWithFiles = testDir.listFiles(startsWithFilter);
            System.out.println("\n以'd'开头的文件:");
            if (startsWithFiles != null) {
                for (File file : startsWithFiles) {
                    System.out.println("  " + file.getName());
                }
            }
            
            // 2. 使用FileFilter
            System.out.println("\n2. 使用FileFilter过滤:");
            
            // 过滤目录
            FileFilter directoryFilter = File::isDirectory;
            File[] directories = testDir.listFiles(directoryFilter);
            System.out.println("目录:");
            if (directories != null) {
                for (File dir : directories) {
                    System.out.println("  " + dir.getName());
                }
            }
            
            // 过滤大于特定大小的文件
            FileFilter sizeFilter = file -> file.isFile() && file.length() > 10;
            File[] largeFiles = testDir.listFiles(sizeFilter);
            System.out.println("\n大于10字节的文件:");
            if (largeFiles != null) {
                for (File file : largeFiles) {
                    System.out.println("  " + file.getName() + " (" + file.length() + " bytes)");
                }
            }
            
            // 3. 复合过滤器
            System.out.println("\n3. 复合过滤器:");
            
            // 文件且以特定扩展名结尾
            FileFilter compoundFilter = file -> 
                file.isFile() && 
                (file.getName().endsWith(".txt") || file.getName().endsWith(".md"));
            
            File[] filteredFiles = testDir.listFiles(compoundFilter);
            System.out.println("文本文件(.txt或.md):");
            if (filteredFiles != null) {
                for (File file : filteredFiles) {
                    System.out.println("  " + file.getName());
                }
            }
            
            // 清理测试目录
            deleteDirectoryRecursively(testDir);
            
        } catch (IOException e) {
            System.err.println("文件过滤演示失败: " + e.getMessage());
        }
    }
}