本章目标

通过本章学习,你将掌握: - 文件和目录操作 - 流的概念和使用 - 文本文件读写 - 二进制文件操作 - JSON序列化和反序列化 - XML序列化和反序列化 - 自定义序列化 - 异步文件操作

1. 文件和目录操作

1.1 基础文件操作

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

public class FileOperationsDemo
{
    private static readonly string BaseDirectory = Path.Combine(Environment.CurrentDirectory, "FileIODemo");
    
    public static void DemonstrateBasicFileOperations()
    {
        Console.WriteLine("=== 基础文件操作演示 ===");
        
        // 确保演示目录存在
        Directory.CreateDirectory(BaseDirectory);
        
        var filePath = Path.Combine(BaseDirectory, "demo.txt");
        var backupPath = Path.Combine(BaseDirectory, "demo_backup.txt");
        
        try
        {
            // 创建文件
            Console.WriteLine("\n--- 文件创建和写入 ---");
            File.WriteAllText(filePath, "这是一个演示文件\n包含多行文本\n用于演示文件操作");
            Console.WriteLine($"文件已创建: {filePath}");
            
            // 检查文件是否存在
            if (File.Exists(filePath))
            {
                Console.WriteLine("文件存在确认");
                
                // 获取文件信息
                var fileInfo = new FileInfo(filePath);
                Console.WriteLine($"文件大小: {fileInfo.Length} 字节");
                Console.WriteLine($"创建时间: {fileInfo.CreationTime}");
                Console.WriteLine($"最后修改时间: {fileInfo.LastWriteTime}");
                Console.WriteLine($"最后访问时间: {fileInfo.LastAccessTime}");
                Console.WriteLine($"文件属性: {fileInfo.Attributes}");
            }
            
            // 读取文件
            Console.WriteLine("\n--- 文件读取 ---");
            var content = File.ReadAllText(filePath);
            Console.WriteLine($"文件内容:\n{content}");
            
            // 复制文件
            Console.WriteLine("\n--- 文件复制 ---");
            File.Copy(filePath, backupPath, true); // true表示覆盖已存在的文件
            Console.WriteLine($"文件已复制到: {backupPath}");
            
            // 移动/重命名文件
            var newPath = Path.Combine(BaseDirectory, "renamed_demo.txt");
            if (File.Exists(newPath))
            {
                File.Delete(newPath);
            }
            File.Move(filePath, newPath);
            Console.WriteLine($"文件已移动到: {newPath}");
            
            // 追加内容
            Console.WriteLine("\n--- 文件追加 ---");
            File.AppendAllText(newPath, "\n这是追加的内容");
            var updatedContent = File.ReadAllText(newPath);
            Console.WriteLine($"追加后的内容:\n{updatedContent}");
            
            // 删除文件
            Console.WriteLine("\n--- 文件删除 ---");
            File.Delete(newPath);
            File.Delete(backupPath);
            Console.WriteLine("演示文件已删除");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"文件操作错误: {ex.Message}");
        }
    }
    
    public static void DemonstrateDirectoryOperations()
    {
        Console.WriteLine("\n=== 目录操作演示 ===");
        
        var demoDir = Path.Combine(BaseDirectory, "DemoDirectory");
        var subDir1 = Path.Combine(demoDir, "SubDir1");
        var subDir2 = Path.Combine(demoDir, "SubDir2");
        
        try
        {
            // 创建目录
            Console.WriteLine("\n--- 目录创建 ---");
            Directory.CreateDirectory(subDir1);
            Directory.CreateDirectory(subDir2);
            Console.WriteLine($"目录已创建: {demoDir}");
            
            // 检查目录是否存在
            if (Directory.Exists(demoDir))
            {
                Console.WriteLine("目录存在确认");
                
                // 获取目录信息
                var dirInfo = new DirectoryInfo(demoDir);
                Console.WriteLine($"目录名称: {dirInfo.Name}");
                Console.WriteLine($"完整路径: {dirInfo.FullName}");
                Console.WriteLine($"父目录: {dirInfo.Parent?.Name}");
                Console.WriteLine($"创建时间: {dirInfo.CreationTime}");
            }
            
            // 在子目录中创建文件
            Console.WriteLine("\n--- 在子目录中创建文件 ---");
            var file1 = Path.Combine(subDir1, "file1.txt");
            var file2 = Path.Combine(subDir1, "file2.log");
            var file3 = Path.Combine(subDir2, "file3.txt");
            
            File.WriteAllText(file1, "这是文件1的内容");
            File.WriteAllText(file2, "这是日志文件的内容");
            File.WriteAllText(file3, "这是文件3的内容");
            
            // 枚举目录内容
            Console.WriteLine("\n--- 枚举目录内容 ---");
            
            // 获取所有文件
            var allFiles = Directory.GetFiles(demoDir, "*", SearchOption.AllDirectories);
            Console.WriteLine($"所有文件 ({allFiles.Length}个):");
            foreach (var file in allFiles)
            {
                Console.WriteLine($"  {Path.GetRelativePath(BaseDirectory, file)}");
            }
            
            // 获取特定扩展名的文件
            var txtFiles = Directory.GetFiles(demoDir, "*.txt", SearchOption.AllDirectories);
            Console.WriteLine($"\n.txt文件 ({txtFiles.Length}个):");
            foreach (var file in txtFiles)
            {
                Console.WriteLine($"  {Path.GetRelativePath(BaseDirectory, file)}");
            }
            
            // 获取所有子目录
            var subDirs = Directory.GetDirectories(demoDir, "*", SearchOption.AllDirectories);
            Console.WriteLine($"\n子目录 ({subDirs.Length}个):");
            foreach (var dir in subDirs)
            {
                Console.WriteLine($"  {Path.GetRelativePath(BaseDirectory, dir)}");
            }
            
            // 使用DirectoryInfo进行更详细的枚举
            Console.WriteLine("\n--- 详细目录信息 ---");
            var dirInfo = new DirectoryInfo(demoDir);
            
            Console.WriteLine("文件信息:");
            foreach (var fileInfo in dirInfo.GetFiles("*", SearchOption.AllDirectories))
            {
                Console.WriteLine($"  {fileInfo.Name}: {fileInfo.Length}字节, {fileInfo.LastWriteTime}");
            }
            
            Console.WriteLine("\n目录信息:");
            foreach (var subDirInfo in dirInfo.GetDirectories("*", SearchOption.AllDirectories))
            {
                var fileCount = subDirInfo.GetFiles().Length;
                Console.WriteLine($"  {subDirInfo.Name}: {fileCount}个文件");
            }
            
            // 删除目录
            Console.WriteLine("\n--- 目录删除 ---");
            Directory.Delete(demoDir, true); // true表示递归删除
            Console.WriteLine("演示目录已删除");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"目录操作错误: {ex.Message}");
        }
    }
    
    public static void DemonstratePathOperations()
    {
        Console.WriteLine("\n=== 路径操作演示 ===");
        
        var filePath = @"C:\Users\Username\Documents\MyFile.txt";
        
        Console.WriteLine($"原始路径: {filePath}");
        Console.WriteLine($"目录名: {Path.GetDirectoryName(filePath)}");
        Console.WriteLine($"文件名: {Path.GetFileName(filePath)}");
        Console.WriteLine($"不含扩展名的文件名: {Path.GetFileNameWithoutExtension(filePath)}");
        Console.WriteLine($"扩展名: {Path.GetExtension(filePath)}");
        Console.WriteLine($"根目录: {Path.GetPathRoot(filePath)}");
        
        // 路径组合
        Console.WriteLine("\n--- 路径组合 ---");
        var combinedPath = Path.Combine("C:", "Users", "Username", "Documents", "NewFile.txt");
        Console.WriteLine($"组合路径: {combinedPath}");
        
        // 相对路径和绝对路径
        Console.WriteLine("\n--- 路径转换 ---");
        var currentDir = Environment.CurrentDirectory;
        var relativePath = "..\\..\\SomeFile.txt";
        var absolutePath = Path.GetFullPath(relativePath);
        
        Console.WriteLine($"当前目录: {currentDir}");
        Console.WriteLine($"相对路径: {relativePath}");
        Console.WriteLine($"绝对路径: {absolutePath}");
        
        // 临时文件和目录
        Console.WriteLine("\n--- 临时文件和目录 ---");
        var tempDir = Path.GetTempPath();
        var tempFile = Path.GetTempFileName();
        var randomTempFile = Path.Combine(tempDir, Path.GetRandomFileName());
        
        Console.WriteLine($"临时目录: {tempDir}");
        Console.WriteLine($"临时文件: {tempFile}");
        Console.WriteLine($"随机文件名: {randomTempFile}");
        
        // 清理临时文件
        if (File.Exists(tempFile))
        {
            File.Delete(tempFile);
        }
        
        // 路径验证
        Console.WriteLine("\n--- 路径验证 ---");
        var validPath = @"C:\Users\Username\Documents\file.txt";
        var invalidPath = @"C:\Users\Username\Documents\<invalid>file.txt";
        
        Console.WriteLine($"有效路径 '{validPath}': {IsValidPath(validPath)}");
        Console.WriteLine($"无效路径 '{invalidPath}': {IsValidPath(invalidPath)}");
    }
    
    private static bool IsValidPath(string path)
    {
        try
        {
            Path.GetFullPath(path);
            return !path.Any(c => Path.GetInvalidPathChars().Contains(c));
        }
        catch
        {
            return false;
        }
    }
}

1.2 高级文件操作

public class AdvancedFileOperationsDemo
{
    private static readonly string BaseDirectory = Path.Combine(Environment.CurrentDirectory, "AdvancedFileDemo");
    
    public static void DemonstrateFileSystemWatcher()
    {
        Console.WriteLine("\n=== 文件系统监视器演示 ===");
        
        Directory.CreateDirectory(BaseDirectory);
        
        using var watcher = new FileSystemWatcher(BaseDirectory)
        {
            NotifyFilter = NotifyFilters.All,
            Filter = "*.*",
            EnableRaisingEvents = true
        };
        
        // 订阅事件
        watcher.Created += (sender, e) => Console.WriteLine($"文件创建: {e.Name}");
        watcher.Changed += (sender, e) => Console.WriteLine($"文件修改: {e.Name}");
        watcher.Deleted += (sender, e) => Console.WriteLine($"文件删除: {e.Name}");
        watcher.Renamed += (sender, e) => Console.WriteLine($"文件重命名: {e.OldName} -> {e.Name}");
        watcher.Error += (sender, e) => Console.WriteLine($"监视器错误: {e.GetException().Message}");
        
        Console.WriteLine($"开始监视目录: {BaseDirectory}");
        Console.WriteLine("按任意键开始文件操作演示...");
        Console.ReadKey();
        
        // 演示文件操作
        var testFile = Path.Combine(BaseDirectory, "test.txt");
        
        Console.WriteLine("\n执行文件操作:");
        File.WriteAllText(testFile, "初始内容");
        Thread.Sleep(100);
        
        File.AppendAllText(testFile, "\n追加内容");
        Thread.Sleep(100);
        
        var renamedFile = Path.Combine(BaseDirectory, "renamed_test.txt");
        if (File.Exists(renamedFile)) File.Delete(renamedFile);
        File.Move(testFile, renamedFile);
        Thread.Sleep(100);
        
        File.Delete(renamedFile);
        
        Console.WriteLine("\n文件操作完成,按任意键停止监视...");
        Console.ReadKey();
        
        // 清理
        Directory.Delete(BaseDirectory, true);
    }
    
    public static void DemonstrateFileAttributes()
    {
        Console.WriteLine("\n=== 文件属性操作演示 ===");
        
        Directory.CreateDirectory(BaseDirectory);
        var testFile = Path.Combine(BaseDirectory, "attributes_test.txt");
        
        try
        {
            // 创建文件
            File.WriteAllText(testFile, "测试文件属性");
            
            // 获取当前属性
            var currentAttributes = File.GetAttributes(testFile);
            Console.WriteLine($"当前属性: {currentAttributes}");
            
            // 设置只读属性
            Console.WriteLine("\n设置只读属性...");
            File.SetAttributes(testFile, currentAttributes | FileAttributes.ReadOnly);
            var readOnlyAttributes = File.GetAttributes(testFile);
            Console.WriteLine($"只读属性: {readOnlyAttributes}");
            Console.WriteLine($"是否只读: {(readOnlyAttributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly}");
            
            // 尝试写入只读文件(会失败)
            try
            {
                File.WriteAllText(testFile, "尝试修改只读文件");
            }
            catch (UnauthorizedAccessException ex)
            {
                Console.WriteLine($"预期的错误: {ex.Message}");
            }
            
            // 移除只读属性
            Console.WriteLine("\n移除只读属性...");
            File.SetAttributes(testFile, currentAttributes & ~FileAttributes.ReadOnly);
            var normalAttributes = File.GetAttributes(testFile);
            Console.WriteLine($"正常属性: {normalAttributes}");
            
            // 现在可以写入
            File.WriteAllText(testFile, "现在可以修改文件了");
            Console.WriteLine("文件修改成功");
            
            // 设置隐藏属性
            Console.WriteLine("\n设置隐藏属性...");
            File.SetAttributes(testFile, normalAttributes | FileAttributes.Hidden);
            var hiddenAttributes = File.GetAttributes(testFile);
            Console.WriteLine($"隐藏属性: {hiddenAttributes}");
            
            // 设置多个属性
            Console.WriteLine("\n设置多个属性...");
            var multipleAttributes = FileAttributes.ReadOnly | FileAttributes.Hidden | FileAttributes.System;
            File.SetAttributes(testFile, multipleAttributes);
            var finalAttributes = File.GetAttributes(testFile);
            Console.WriteLine($"多重属性: {finalAttributes}");
            
            // 检查特定属性
            Console.WriteLine("\n属性检查:");
            Console.WriteLine($"是否只读: {HasAttribute(finalAttributes, FileAttributes.ReadOnly)}");
            Console.WriteLine($"是否隐藏: {HasAttribute(finalAttributes, FileAttributes.Hidden)}");
            Console.WriteLine($"是否系统文件: {HasAttribute(finalAttributes, FileAttributes.System)}");
            Console.WriteLine($"是否目录: {HasAttribute(finalAttributes, FileAttributes.Directory)}");
        }
        finally
        {
            // 清理:先移除只读属性,然后删除
            if (File.Exists(testFile))
            {
                File.SetAttributes(testFile, FileAttributes.Normal);
                File.Delete(testFile);
            }
            Directory.Delete(BaseDirectory, true);
        }
    }
    
    private static bool HasAttribute(FileAttributes attributes, FileAttributes flag)
    {
        return (attributes & flag) == flag;
    }
    
    public static void DemonstrateFileSecurity()
    {
        Console.WriteLine("\n=== 文件安全和权限演示 ===");
        
        Directory.CreateDirectory(BaseDirectory);
        var testFile = Path.Combine(BaseDirectory, "security_test.txt");
        
        try
        {
            // 创建文件
            File.WriteAllText(testFile, "安全测试文件");
            
            // 获取文件信息
            var fileInfo = new FileInfo(testFile);
            Console.WriteLine($"文件: {fileInfo.Name}");
            Console.WriteLine($"大小: {fileInfo.Length} 字节");
            Console.WriteLine($"创建时间: {fileInfo.CreationTime}");
            Console.WriteLine($"修改时间: {fileInfo.LastWriteTime}");
            Console.WriteLine($"访问时间: {fileInfo.LastAccessTime}");
            
            // 检查文件是否可读写
            Console.WriteLine("\n权限检查:");
            Console.WriteLine($"文件存在: {fileInfo.Exists}");
            Console.WriteLine($"是否只读: {fileInfo.IsReadOnly}");
            
            // 尝试不同的访问模式
            Console.WriteLine("\n访问模式测试:");
            
            // 测试读取权限
            try
            {
                using var readStream = File.OpenRead(testFile);
                Console.WriteLine("读取权限: 可用");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"读取权限: 不可用 - {ex.Message}");
            }
            
            // 测试写入权限
            try
            {
                using var writeStream = File.OpenWrite(testFile);
                Console.WriteLine("写入权限: 可用");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"写入权限: 不可用 - {ex.Message}");
            }
            
            // 设置只读并重新测试
            Console.WriteLine("\n设置只读后重新测试:");
            fileInfo.IsReadOnly = true;
            
            try
            {
                using var writeStream = File.OpenWrite(testFile);
                Console.WriteLine("写入权限: 可用");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"写入权限: 不可用 - {ex.Message}");
            }
            
            // 恢复写入权限
            fileInfo.IsReadOnly = false;
        }
        finally
        {
            // 清理
            if (File.Exists(testFile))
            {
                var fileInfo = new FileInfo(testFile);
                fileInfo.IsReadOnly = false;
                File.Delete(testFile);
            }
            Directory.Delete(BaseDirectory, true);
        }
    }
}

2. 流操作

2.1 基础流操作

public class StreamOperationsDemo
{
    private static readonly string BaseDirectory = Path.Combine(Environment.CurrentDirectory, "StreamDemo");
    
    public static void DemonstrateBasicStreams()
    {
        Console.WriteLine("\n=== 基础流操作演示 ===");
        
        Directory.CreateDirectory(BaseDirectory);
        var filePath = Path.Combine(BaseDirectory, "stream_demo.txt");
        
        // FileStream 基础操作
        Console.WriteLine("\n--- FileStream操作 ---");
        
        // 写入数据
        using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
        {
            var data = Encoding.UTF8.GetBytes("Hello, FileStream!\n这是中文测试\n");
            fileStream.Write(data, 0, data.Length);
            Console.WriteLine($"写入 {data.Length} 字节到文件");
        }
        
        // 读取数据
        using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            var buffer = new byte[fileStream.Length];
            var bytesRead = fileStream.Read(buffer, 0, buffer.Length);
            var content = Encoding.UTF8.GetString(buffer, 0, bytesRead);
            Console.WriteLine($"从文件读取 {bytesRead} 字节:");
            Console.WriteLine(content);
        }
        
        // MemoryStream 操作
        Console.WriteLine("\n--- MemoryStream操作 ---");
        
        using var memoryStream = new MemoryStream();
        var testData = Encoding.UTF8.GetBytes("这是内存流测试数据\n包含多行内容\n");
        
        // 写入内存流
        memoryStream.Write(testData, 0, testData.Length);
        Console.WriteLine($"写入 {testData.Length} 字节到内存流");
        
        // 重置位置并读取
        memoryStream.Position = 0;
        var readBuffer = new byte[memoryStream.Length];
        var bytesRead2 = memoryStream.Read(readBuffer, 0, readBuffer.Length);
        var memoryContent = Encoding.UTF8.GetString(readBuffer, 0, bytesRead2);
        Console.WriteLine($"从内存流读取 {bytesRead2} 字节:");
        Console.WriteLine(memoryContent);
        
        // 获取内存流的字节数组
        var allBytes = memoryStream.ToArray();
        Console.WriteLine($"内存流总字节数: {allBytes.Length}");
        
        // BufferedStream 操作
        Console.WriteLine("\n--- BufferedStream操作 ---");
        
        var bufferedFile = Path.Combine(BaseDirectory, "buffered_demo.txt");
        
        // 使用缓冲流写入
        using (var fileStream = new FileStream(bufferedFile, FileMode.Create))
        using (var bufferedStream = new BufferedStream(fileStream, 4096)) // 4KB缓冲区
        {
            for (int i = 0; i < 1000; i++)
            {
                var line = $"这是第 {i + 1} 行数据\n";
                var lineBytes = Encoding.UTF8.GetBytes(line);
                bufferedStream.Write(lineBytes, 0, lineBytes.Length);
            }
            Console.WriteLine("使用缓冲流写入1000行数据");
        }
        
        // 使用缓冲流读取
        using (var fileStream = new FileStream(bufferedFile, FileMode.Open))
        using (var bufferedStream = new BufferedStream(fileStream, 4096))
        {
            var buffer = new byte[1024];
            var totalBytesRead = 0;
            int bytesRead;
            
            while ((bytesRead = bufferedStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                totalBytesRead += bytesRead;
            }
            
            Console.WriteLine($"使用缓冲流读取总计 {totalBytesRead} 字节");
        }
        
        // 清理
        File.Delete(filePath);
        File.Delete(bufferedFile);
        Directory.Delete(BaseDirectory);
    }
    
    public static void DemonstrateStreamReaderWriter()
    {
        Console.WriteLine("\n=== StreamReader/StreamWriter演示 ===");
        
        Directory.CreateDirectory(BaseDirectory);
        var textFile = Path.Combine(BaseDirectory, "text_demo.txt");
        
        // StreamWriter 写入文本
        Console.WriteLine("\n--- StreamWriter操作 ---");
        
        using (var writer = new StreamWriter(textFile, false, Encoding.UTF8))
        {
            writer.WriteLine("这是第一行");
            writer.WriteLine("这是第二行");
            writer.Write("这是不换行的文本");
            writer.Write(" 继续在同一行");
            writer.WriteLine(); // 手动换行
            writer.WriteLine($"当前时间: {DateTime.Now}");
            
            // 写入数组
            var lines = new[] { "数组第一行", "数组第二行", "数组第三行" };
            foreach (var line in lines)
            {
                writer.WriteLine(line);
            }
            
            Console.WriteLine("文本写入完成");
        }
        
        // StreamReader 读取文本
        Console.WriteLine("\n--- StreamReader操作 ---");
        
        using (var reader = new StreamReader(textFile, Encoding.UTF8))
        {
            Console.WriteLine("逐行读取:");
            string line;
            int lineNumber = 1;
            
            while ((line = reader.ReadLine()) != null)
            {
                Console.WriteLine($"  {lineNumber:D2}: {line}");
                lineNumber++;
            }
        }
        
        // 一次性读取所有内容
        Console.WriteLine("\n--- 一次性读取 ---");
        using (var reader = new StreamReader(textFile, Encoding.UTF8))
        {
            var allContent = reader.ReadToEnd();
            Console.WriteLine($"文件总内容 ({allContent.Length} 字符):");
            Console.WriteLine(allContent);
        }
        
        // 读取指定字符数
        Console.WriteLine("\n--- 读取指定字符数 ---");
        using (var reader = new StreamReader(textFile, Encoding.UTF8))
        {
            var buffer = new char[20];
            var charsRead = reader.Read(buffer, 0, buffer.Length);
            var partialContent = new string(buffer, 0, charsRead);
            Console.WriteLine($"读取前 {charsRead} 个字符: '{partialContent}'");
        }
        
        // 追加模式写入
        Console.WriteLine("\n--- 追加模式写入 ---");
        using (var writer = new StreamWriter(textFile, true, Encoding.UTF8)) // true表示追加
        {
            writer.WriteLine($"\n追加时间: {DateTime.Now}");
            writer.WriteLine("这是追加的内容");
        }
        
        // 验证追加结果
        var finalContent = File.ReadAllText(textFile, Encoding.UTF8);
        Console.WriteLine($"\n最终文件内容:\n{finalContent}");
        
        // 清理
        File.Delete(textFile);
        Directory.Delete(BaseDirectory);
    }
    
    public static void DemonstrateBinaryReaderWriter()
    {
        Console.WriteLine("\n=== BinaryReader/BinaryWriter演示 ===");
        
        Directory.CreateDirectory(BaseDirectory);
        var binaryFile = Path.Combine(BaseDirectory, "binary_demo.dat");
        
        // BinaryWriter 写入二进制数据
        Console.WriteLine("\n--- BinaryWriter操作 ---");
        
        using (var fileStream = new FileStream(binaryFile, FileMode.Create))
        using (var writer = new BinaryWriter(fileStream, Encoding.UTF8))
        {
            // 写入各种数据类型
            writer.Write(true);                    // bool
            writer.Write((byte)255);               // byte
            writer.Write((short)32767);            // short
            writer.Write(2147483647);              // int
            writer.Write(9223372036854775807L);    // long
            writer.Write(3.14159f);                // float
            writer.Write(2.718281828459045);       // double
            writer.Write('A');                     // char
            writer.Write("Hello, Binary World!"); // string
            
            // 写入字节数组
            var byteArray = new byte[] { 1, 2, 3, 4, 5 };
            writer.Write(byteArray.Length);
            writer.Write(byteArray);
            
            // 写入日期时间(作为二进制)
            var now = DateTime.Now;
            writer.Write(now.ToBinary());
            
            Console.WriteLine("二进制数据写入完成");
        }
        
        // BinaryReader 读取二进制数据
        Console.WriteLine("\n--- BinaryReader操作 ---");
        
        using (var fileStream = new FileStream(binaryFile, FileMode.Open))
        using (var reader = new BinaryReader(fileStream, Encoding.UTF8))
        {
            // 按写入顺序读取数据
            var boolValue = reader.ReadBoolean();
            var byteValue = reader.ReadByte();
            var shortValue = reader.ReadInt16();
            var intValue = reader.ReadInt32();
            var longValue = reader.ReadInt64();
            var floatValue = reader.ReadSingle();
            var doubleValue = reader.ReadDouble();
            var charValue = reader.ReadChar();
            var stringValue = reader.ReadString();
            
            // 读取字节数组
            var arrayLength = reader.ReadInt32();
            var byteArray = reader.ReadBytes(arrayLength);
            
            // 读取日期时间
            var dateTimeBinary = reader.ReadInt64();
            var dateTimeValue = DateTime.FromBinary(dateTimeBinary);
            
            // 显示读取的数据
            Console.WriteLine($"Boolean: {boolValue}");
            Console.WriteLine($"Byte: {byteValue}");
            Console.WriteLine($"Short: {shortValue}");
            Console.WriteLine($"Int: {intValue}");
            Console.WriteLine($"Long: {longValue}");
            Console.WriteLine($"Float: {floatValue}");
            Console.WriteLine($"Double: {doubleValue}");
            Console.WriteLine($"Char: {charValue}");
            Console.WriteLine($"String: {stringValue}");
            Console.WriteLine($"Byte Array: [{string.Join(", ", byteArray)}]");
            Console.WriteLine($"DateTime: {dateTimeValue}");
        }
        
        // 文件大小信息
        var fileInfo = new FileInfo(binaryFile);
        Console.WriteLine($"\n二进制文件大小: {fileInfo.Length} 字节");
        
        // 清理
        File.Delete(binaryFile);
        Directory.Delete(BaseDirectory);
     }
 }

8. 实践练习

8.1 日志管理系统

public enum LogLevel
{
    Debug,
    Info,
    Warning,
    Error,
    Fatal
}

public class LogEntry
{
    public DateTime Timestamp { get; set; }
    public LogLevel Level { get; set; }
    public string Category { get; set; }
    public string Message { get; set; }
    public string Exception { get; set; }
    public string ThreadId { get; set; }
    public Dictionary<string, object> Properties { get; set; }
    
    public LogEntry()
    {
        Properties = new Dictionary<string, object>();
    }
}

public interface ILogWriter
{
    Task WriteAsync(LogEntry entry);
    Task FlushAsync();
}

public class FileLogWriter : ILogWriter
{
    private readonly string _logDirectory;
    private readonly string _fileNamePattern;
    private readonly SemaphoreSlim _semaphore;
    
    public FileLogWriter(string logDirectory, string fileNamePattern = "log_{0:yyyy-MM-dd}.txt")
    {
        _logDirectory = logDirectory;
        _fileNamePattern = fileNamePattern;
        _semaphore = new SemaphoreSlim(1, 1);
        
        Directory.CreateDirectory(_logDirectory);
    }
    
    public async Task WriteAsync(LogEntry entry)
    {
        var fileName = string.Format(_fileNamePattern, entry.Timestamp);
        var filePath = Path.Combine(_logDirectory, fileName);
        
        var logLine = FormatLogEntry(entry);
        
        await _semaphore.WaitAsync();
        try
        {
            await File.AppendAllTextAsync(filePath, logLine + Environment.NewLine, Encoding.UTF8);
        }
        finally
        {
            _semaphore.Release();
        }
    }
    
    public async Task FlushAsync()
    {
        // 文件写入是立即的,这里可以实现缓冲区刷新逻辑
        await Task.CompletedTask;
    }
    
    private string FormatLogEntry(LogEntry entry)
    {
        var sb = new StringBuilder();
        sb.Append($"[{entry.Timestamp:yyyy-MM-dd HH:mm:ss.fff}]");
        sb.Append($" [{entry.Level}]");
        sb.Append($" [{entry.Category}]");
        sb.Append($" [{entry.ThreadId}]");
        sb.Append($" {entry.Message}");
        
        if (!string.IsNullOrEmpty(entry.Exception))
        {
            sb.Append($" | Exception: {entry.Exception}");
        }
        
        if (entry.Properties.Any())
        {
            sb.Append(" | Properties: ");
            sb.Append(string.Join(", ", entry.Properties.Select(kvp => $"{kvp.Key}={kvp.Value}")));
        }
        
        return sb.ToString();
    }
}

public class JsonLogWriter : ILogWriter
{
    private readonly string _logFile;
    private readonly SemaphoreSlim _semaphore;
    private readonly JsonSerializerOptions _jsonOptions;
    
    public JsonLogWriter(string logFile)
    {
        _logFile = logFile;
        _semaphore = new SemaphoreSlim(1, 1);
        _jsonOptions = new JsonSerializerOptions
        {
            WriteIndented = false,
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        };
        
        Directory.CreateDirectory(Path.GetDirectoryName(_logFile));
    }
    
    public async Task WriteAsync(LogEntry entry)
    {
        var json = JsonSerializer.Serialize(entry, _jsonOptions);
        
        await _semaphore.WaitAsync();
        try
        {
            await File.AppendAllTextAsync(_logFile, json + Environment.NewLine, Encoding.UTF8);
        }
        finally
        {
            _semaphore.Release();
        }
    }
    
    public async Task FlushAsync()
    {
        await Task.CompletedTask;
    }
}

public class Logger
{
    private readonly List<ILogWriter> _writers;
    private readonly string _category;
    
    public Logger(string category, params ILogWriter[] writers)
    {
        _category = category;
        _writers = new List<ILogWriter>(writers);
    }
    
    public async Task LogAsync(LogLevel level, string message, Exception exception = null, Dictionary<string, object> properties = null)
    {
        var entry = new LogEntry
        {
            Timestamp = DateTime.Now,
            Level = level,
            Category = _category,
            Message = message,
            Exception = exception?.ToString(),
            ThreadId = Thread.CurrentThread.ManagedThreadId.ToString(),
            Properties = properties ?? new Dictionary<string, object>()
        };
        
        var writeTasks = _writers.Select(writer => writer.WriteAsync(entry));
        await Task.WhenAll(writeTasks);
    }
    
    public Task DebugAsync(string message, Dictionary<string, object> properties = null) => LogAsync(LogLevel.Debug, message, null, properties);
    public Task InfoAsync(string message, Dictionary<string, object> properties = null) => LogAsync(LogLevel.Info, message, null, properties);
    public Task WarningAsync(string message, Dictionary<string, object> properties = null) => LogAsync(LogLevel.Warning, message, null, properties);
    public Task ErrorAsync(string message, Exception exception = null, Dictionary<string, object> properties = null) => LogAsync(LogLevel.Error, message, exception, properties);
    public Task FatalAsync(string message, Exception exception = null, Dictionary<string, object> properties = null) => LogAsync(LogLevel.Fatal, message, exception, properties);
}

public class LoggingSystemDemo
{
    public static async Task DemonstrateLoggingSystem()
    {
        Console.WriteLine("\n=== 日志管理系统演示 ===");
        
        var logDirectory = Path.Combine(Environment.CurrentDirectory, "Logs");
        var jsonLogFile = Path.Combine(logDirectory, "application.json");
        
        // 创建日志写入器
        var fileWriter = new FileLogWriter(logDirectory);
        var jsonWriter = new JsonLogWriter(jsonLogFile);
        
        // 创建日志记录器
        var logger = new Logger("DemoApplication", fileWriter, jsonWriter);
        
        Console.WriteLine("\n--- 记录各种级别的日志 ---");
        
        await logger.DebugAsync("应用程序启动", new Dictionary<string, object> { { "Version", "1.0.0" }, { "Environment", "Development" } });
        await logger.InfoAsync("用户登录成功", new Dictionary<string, object> { { "UserId", 12345 }, { "UserName", "张三" } });
        await logger.WarningAsync("数据库连接缓慢", new Dictionary<string, object> { { "ResponseTime", 5000 }, { "Database", "UserDB" } });
        
        try
        {
            throw new InvalidOperationException("模拟业务异常");
        }
        catch (Exception ex)
        {
            await logger.ErrorAsync("业务操作失败", ex, new Dictionary<string, object> { { "Operation", "CreateUser" }, { "UserId", 67890 } });
        }
        
        await logger.FatalAsync("系统即将关闭", null, new Dictionary<string, object> { { "Reason", "Critical Error" } });
        
        Console.WriteLine("日志记录完成");
        
        // 读取并显示日志文件
        Console.WriteLine("\n--- 文本日志内容 ---");
        var textLogFiles = Directory.GetFiles(logDirectory, "log_*.txt");
        foreach (var logFile in textLogFiles)
        {
            Console.WriteLine($"\n文件: {Path.GetFileName(logFile)}");
            var content = await File.ReadAllTextAsync(logFile, Encoding.UTF8);
            Console.WriteLine(content);
        }
        
        Console.WriteLine("\n--- JSON日志内容 ---");
        if (File.Exists(jsonLogFile))
        {
            var jsonLines = await File.ReadAllLinesAsync(jsonLogFile, Encoding.UTF8);
            foreach (var line in jsonLines)
            {
                var logEntry = JsonSerializer.Deserialize<LogEntry>(line, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
                Console.WriteLine($"[{logEntry.Timestamp:HH:mm:ss}] {logEntry.Level}: {logEntry.Message}");
            }
        }
        
        // 清理
        Directory.Delete(logDirectory, true);
    }
}

8.2 配置管理系统

public class DatabaseConfig
{
    public string ConnectionString { get; set; }
    public int CommandTimeout { get; set; }
    public bool EnableRetry { get; set; }
    public int MaxRetryCount { get; set; }
}

public class CacheConfig
{
    public string Provider { get; set; }
    public string ConnectionString { get; set; }
    public int DefaultExpiration { get; set; }
    public Dictionary<string, int> CategoryExpirations { get; set; }
    
    public CacheConfig()
    {
        CategoryExpirations = new Dictionary<string, int>();
    }
}

public class LoggingConfig
{
    public string Level { get; set; }
    public List<string> Providers { get; set; }
    public Dictionary<string, object> Settings { get; set; }
    
    public LoggingConfig()
    {
        Providers = new List<string>();
        Settings = new Dictionary<string, object>();
    }
}

public class ApplicationConfig
{
    public string ApplicationName { get; set; }
    public string Version { get; set; }
    public string Environment { get; set; }
    public DatabaseConfig Database { get; set; }
    public CacheConfig Cache { get; set; }
    public LoggingConfig Logging { get; set; }
    public Dictionary<string, object> CustomSettings { get; set; }
    
    public ApplicationConfig()
    {
        CustomSettings = new Dictionary<string, object>();
    }
}

public class ConfigurationManager
{
    private readonly string _configDirectory;
    private readonly Dictionary<string, object> _configurations;
    private readonly FileSystemWatcher _watcher;
    
    public event Action<string, object> ConfigurationChanged;
    
    public ConfigurationManager(string configDirectory)
    {
        _configDirectory = configDirectory;
        _configurations = new Dictionary<string, object>();
        
        Directory.CreateDirectory(_configDirectory);
        
        // 设置文件监视器
        _watcher = new FileSystemWatcher(_configDirectory, "*.json")
        {
            NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName,
            EnableRaisingEvents = true
        };
        
        _watcher.Changed += OnConfigFileChanged;
        _watcher.Created += OnConfigFileChanged;
    }
    
    public async Task<T> LoadConfigurationAsync<T>(string configName) where T : class, new()
    {
        var configFile = Path.Combine(_configDirectory, $"{configName}.json");
        
        if (!File.Exists(configFile))
        {
            var defaultConfig = new T();
            await SaveConfigurationAsync(configName, defaultConfig);
            return defaultConfig;
        }
        
        var json = await File.ReadAllTextAsync(configFile, Encoding.UTF8);
        var config = JsonSerializer.Deserialize<T>(json, new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            WriteIndented = true
        });
        
        _configurations[configName] = config;
        return config;
    }
    
    public async Task SaveConfigurationAsync<T>(string configName, T configuration)
    {
        var configFile = Path.Combine(_configDirectory, $"{configName}.json");
        
        var json = JsonSerializer.Serialize(configuration, new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            WriteIndented = true,
            Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
        });
        
        await File.WriteAllTextAsync(configFile, json, Encoding.UTF8);
        _configurations[configName] = configuration;
    }
    
    public T GetConfiguration<T>(string configName) where T : class
    {
        return _configurations.TryGetValue(configName, out var config) ? config as T : null;
    }
    
    private async void OnConfigFileChanged(object sender, FileSystemEventArgs e)
    {
        try
        {
            await Task.Delay(100); // 等待文件写入完成
            
            var configName = Path.GetFileNameWithoutExtension(e.Name);
            
            if (_configurations.ContainsKey(configName))
            {
                var configType = _configurations[configName].GetType();
                var method = typeof(ConfigurationManager).GetMethod(nameof(LoadConfigurationAsync));
                var genericMethod = method.MakeGenericMethod(configType);
                
                var task = (Task)genericMethod.Invoke(this, new object[] { configName });
                await task;
                
                var property = task.GetType().GetProperty("Result");
                var newConfig = property.GetValue(task);
                
                ConfigurationChanged?.Invoke(configName, newConfig);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"配置文件变更处理错误: {ex.Message}");
        }
    }
    
    public void Dispose()
    {
        _watcher?.Dispose();
    }
}

public class ConfigurationSystemDemo
{
    public static async Task DemonstrateConfigurationSystem()
    {
        Console.WriteLine("\n=== 配置管理系统演示 ===");
        
        var configDirectory = Path.Combine(Environment.CurrentDirectory, "Config");
        var configManager = new ConfigurationManager(configDirectory);
        
        // 监听配置变更
        configManager.ConfigurationChanged += (configName, newConfig) =>
        {
            Console.WriteLine($"\n配置 '{configName}' 已更新");
        };
        
        Console.WriteLine("\n--- 创建和保存配置 ---");
        
        // 创建应用程序配置
        var appConfig = new ApplicationConfig
        {
            ApplicationName = "演示应用",
            Version = "1.0.0",
            Environment = "Development",
            Database = new DatabaseConfig
            {
                ConnectionString = "Server=localhost;Database=DemoApp;Trusted_Connection=true;",
                CommandTimeout = 30,
                EnableRetry = true,
                MaxRetryCount = 3
            },
            Cache = new CacheConfig
            {
                Provider = "Redis",
                ConnectionString = "localhost:6379",
                DefaultExpiration = 3600,
                CategoryExpirations = new Dictionary<string, int>
                {
                    { "User", 1800 },
                    { "Product", 7200 },
                    { "Session", 900 }
                }
            },
            Logging = new LoggingConfig
            {
                Level = "Information",
                Providers = new List<string> { "File", "Console", "Database" },
                Settings = new Dictionary<string, object>
                {
                    { "FileLogPath", "logs/app.log" },
                    { "MaxFileSize", 10485760 },
                    { "RetainDays", 30 }
                }
            },
            CustomSettings = new Dictionary<string, object>
            {
                { "FeatureFlags", new Dictionary<string, bool>
                    {
                        { "EnableNewUI", true },
                        { "EnableBetaFeatures", false }
                    }
                },
                { "ApiSettings", new Dictionary<string, object>
                    {
                        { "BaseUrl", "https://api.example.com" },
                        { "Timeout", 30000 },
                        { "ApiKey", "your-api-key-here" }
                    }
                }
            }
        };
        
        await configManager.SaveConfigurationAsync("application", appConfig);
        Console.WriteLine("应用程序配置已保存");
        
        Console.WriteLine("\n--- 加载配置 ---");
        
        var loadedConfig = await configManager.LoadConfigurationAsync<ApplicationConfig>("application");
        
        Console.WriteLine($"应用程序: {loadedConfig.ApplicationName} v{loadedConfig.Version}");
        Console.WriteLine($"环境: {loadedConfig.Environment}");
        Console.WriteLine($"数据库超时: {loadedConfig.Database.CommandTimeout}秒");
        Console.WriteLine($"缓存提供者: {loadedConfig.Cache.Provider}");
        Console.WriteLine($"日志级别: {loadedConfig.Logging.Level}");
        Console.WriteLine($"日志提供者: {string.Join(", ", loadedConfig.Logging.Providers)}");
        
        Console.WriteLine("\n--- 显示配置文件内容 ---");
        var configFile = Path.Combine(configDirectory, "application.json");
        var configContent = await File.ReadAllTextAsync(configFile, Encoding.UTF8);
        Console.WriteLine(configContent);
        
        // 清理
        configManager.Dispose();
        Directory.Delete(configDirectory, true);
    }
}

9. 最佳实践

9.1 性能优化

  1. 使用异步操作:对于I/O密集型操作,始终使用异步方法
  2. 缓冲区大小:根据文件大小和操作类型选择合适的缓冲区大小
  3. 流的重用:在可能的情况下重用流对象
  4. 及时释放资源:使用using语句确保资源正确释放

9.2 错误处理

  1. 异常处理:妥善处理文件操作可能出现的异常
  2. 重试机制:对于网络文件操作,实现重试机制
  3. 日志记录:记录文件操作的详细信息用于调试

9.3 安全性

  1. 路径验证:验证文件路径,防止路径遍历攻击
  2. 权限检查:在操作文件前检查必要的权限
  3. 敏感数据加密:对敏感数据进行加密存储
  4. 输入验证:验证用户输入的文件名和路径

9.4 可维护性

  1. 配置外部化:将文件路径和配置信息外部化
  2. 接口抽象:使用接口抽象文件操作,便于测试和替换
  3. 单一职责:每个类只负责特定的文件操作功能
  4. 文档注释:为复杂的文件操作添加详细注释

10. 章节总结

本章详细介绍了C#中的文件I/O和序列化技术:

核心概念

  • 文件和目录操作:使用FileDirectoryPath类进行基础操作
  • 流操作:理解和使用各种流类型进行数据读写
  • 序列化:掌握JSON、XML等格式的序列化和反序列化
  • 异步操作:使用异步方法提高I/O操作性能

重要技能

  • 能够进行各种文件和目录操作
  • 掌握文本和二进制文件的读写
  • 理解并应用不同的序列化技术
  • 实现自定义序列化逻辑
  • 使用异步操作提高应用程序性能

实际应用

  • 日志管理系统
  • 配置管理系统
  • 数据持久化
  • 文件处理工具
  • 数据交换和API通信

文件I/O和序列化是现代应用程序的基础技能,掌握这些技术将帮助你构建更加健壮和高效的应用程序。

下一章我们将学习多线程和并发编程,探讨如何在C#中实现并发和并行处理。

2.2 高级流操作

public class AdvancedStreamDemo
{
    private static readonly string BaseDirectory = Path.Combine(Environment.CurrentDirectory, "AdvancedStreamDemo");
    
    public static void DemonstrateCompressionStreams()
    {
        Console.WriteLine("\n=== 压缩流演示 ===");
        
        Directory.CreateDirectory(BaseDirectory);
        
        // 准备测试数据
        var originalData = string.Join("\n", Enumerable.Range(1, 1000)
            .Select(i => $"这是第 {i} 行重复的测试数据,用于演示压缩效果。"));
        var originalBytes = Encoding.UTF8.GetBytes(originalData);
        
        Console.WriteLine($"原始数据大小: {originalBytes.Length} 字节");
        
        // GZip 压缩
        var gzipFile = Path.Combine(BaseDirectory, "compressed.gz");
        
        using (var fileStream = new FileStream(gzipFile, FileMode.Create))
        using (var gzipStream = new System.IO.Compression.GZipStream(fileStream, System.IO.Compression.CompressionMode.Compress))
        {
            gzipStream.Write(originalBytes, 0, originalBytes.Length);
        }
        
        var compressedSize = new FileInfo(gzipFile).Length;
        Console.WriteLine($"GZip压缩后大小: {compressedSize} 字节");
        Console.WriteLine($"压缩比: {(double)compressedSize / originalBytes.Length:P2}");
        
        // GZip 解压缩
        using (var fileStream = new FileStream(gzipFile, FileMode.Open))
        using (var gzipStream = new System.IO.Compression.GZipStream(fileStream, System.IO.Compression.CompressionMode.Decompress))
        using (var memoryStream = new MemoryStream())
        {
            gzipStream.CopyTo(memoryStream);
            var decompressedBytes = memoryStream.ToArray();
            var decompressedData = Encoding.UTF8.GetString(decompressedBytes);
            
            Console.WriteLine($"解压缩后大小: {decompressedBytes.Length} 字节");
            Console.WriteLine($"数据完整性: {(originalData == decompressedData ? "正确" : "错误")}");
        }
        
        // Deflate 压缩
        var deflateFile = Path.Combine(BaseDirectory, "compressed.deflate");
        
        using (var fileStream = new FileStream(deflateFile, FileMode.Create))
        using (var deflateStream = new System.IO.Compression.DeflateStream(fileStream, System.IO.Compression.CompressionMode.Compress))
        {
            deflateStream.Write(originalBytes, 0, originalBytes.Length);
        }
        
        var deflateSize = new FileInfo(deflateFile).Length;
        Console.WriteLine($"\nDeflate压缩后大小: {deflateSize} 字节");
        Console.WriteLine($"压缩比: {(double)deflateSize / originalBytes.Length:P2}");
        
        // 清理
        File.Delete(gzipFile);
        File.Delete(deflateFile);
        Directory.Delete(BaseDirectory);
    }
    
    public static void DemonstrateStreamCombination()
    {
        Console.WriteLine("\n=== 流组合演示 ===");
        
        Directory.CreateDirectory(BaseDirectory);
        
        var testData = "这是一个测试字符串,将通过多层流处理。\n" +
                      "包含中文字符和特殊符号:@#$%^&*()\n" +
                      "用于演示流的组合使用。";
        
        var combinedFile = Path.Combine(BaseDirectory, "combined_stream.dat");
        
        // 写入:FileStream -> BufferedStream -> GZipStream -> BinaryWriter
        Console.WriteLine("\n--- 多层流写入 ---");
        
        using (var fileStream = new FileStream(combinedFile, FileMode.Create))
        using (var bufferedStream = new BufferedStream(fileStream, 4096))
        using (var gzipStream = new System.IO.Compression.GZipStream(bufferedStream, System.IO.Compression.CompressionMode.Compress))
        using (var binaryWriter = new BinaryWriter(gzipStream, Encoding.UTF8))
        {
            // 写入元数据
            binaryWriter.Write(DateTime.Now.ToBinary());
            binaryWriter.Write("TestFile");
            binaryWriter.Write(1); // 版本号
            
            // 写入实际数据
            binaryWriter.Write(testData);
            
            Console.WriteLine("数据通过多层流写入完成");
        }
        
        var fileSize = new FileInfo(combinedFile).Length;
        Console.WriteLine($"文件大小: {fileSize} 字节");
        
        // 读取:FileStream -> BufferedStream -> GZipStream -> BinaryReader
        Console.WriteLine("\n--- 多层流读取 ---");
        
        using (var fileStream = new FileStream(combinedFile, FileMode.Open))
        using (var bufferedStream = new BufferedStream(fileStream, 4096))
        using (var gzipStream = new System.IO.Compression.GZipStream(bufferedStream, System.IO.Compression.CompressionMode.Decompress))
        using (var binaryReader = new BinaryReader(gzipStream, Encoding.UTF8))
        {
            // 读取元数据
            var timestamp = DateTime.FromBinary(binaryReader.ReadInt64());
            var filename = binaryReader.ReadString();
            var version = binaryReader.ReadInt32();
            
            // 读取实际数据
            var readData = binaryReader.ReadString();
            
            Console.WriteLine($"时间戳: {timestamp}");
            Console.WriteLine($"文件名: {filename}");
            Console.WriteLine($"版本: {version}");
            Console.WriteLine($"数据完整性: {(testData == readData ? "正确" : "错误")}");
            Console.WriteLine($"读取的数据:\n{readData}");
        }
        
        // 清理
        File.Delete(combinedFile);
        Directory.Delete(BaseDirectory);
    }
    
    public static void DemonstrateCustomStream()
    {
        Console.WriteLine("\n=== 自定义流演示 ===");
        
        // 使用自定义的计数流
        using var countingStream = new CountingStream(new MemoryStream());
        using var writer = new StreamWriter(countingStream, Encoding.UTF8);
        
        writer.WriteLine("第一行数据");
        writer.WriteLine("第二行数据");
        writer.WriteLine("第三行数据");
        writer.Flush();
        
        Console.WriteLine($"写入字节数: {countingStream.BytesWritten}");
        Console.WriteLine($"写入次数: {countingStream.WriteCount}");
        
        // 重置位置并读取
        countingStream.Position = 0;
        using var reader = new StreamReader(countingStream, Encoding.UTF8);
        
        var content = reader.ReadToEnd();
        Console.WriteLine($"读取字节数: {countingStream.BytesRead}");
        Console.WriteLine($"读取次数: {countingStream.ReadCount}");
        Console.WriteLine($"读取内容:\n{content}");
    }
}

// 自定义计数流
public class CountingStream : Stream
{
    private readonly Stream _baseStream;
    
    public long BytesRead { get; private set; }
    public long BytesWritten { get; private set; }
    public int ReadCount { get; private set; }
    public int WriteCount { get; private set; }
    
    public CountingStream(Stream baseStream)
    {
        _baseStream = baseStream ?? throw new ArgumentNullException(nameof(baseStream));
    }
    
    public override bool CanRead => _baseStream.CanRead;
    public override bool CanSeek => _baseStream.CanSeek;
    public override bool CanWrite => _baseStream.CanWrite;
    public override long Length => _baseStream.Length;
    
    public override long Position
    {
        get => _baseStream.Position;
        set => _baseStream.Position = value;
    }
    
    public override void Flush() => _baseStream.Flush();
    
    public override int Read(byte[] buffer, int offset, int count)
    {
        var bytesRead = _baseStream.Read(buffer, offset, count);
        BytesRead += bytesRead;
        ReadCount++;
        return bytesRead;
    }
    
    public override long Seek(long offset, SeekOrigin origin)
    {
        return _baseStream.Seek(offset, origin);
    }
    
    public override void SetLength(long value)
    {
        _baseStream.SetLength(value);
    }
    
    public override void Write(byte[] buffer, int offset, int count)
    {
        _baseStream.Write(buffer, offset, count);
        BytesWritten += count;
        WriteCount++;
    }
    
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _baseStream?.Dispose();
        }
        base.Dispose(disposing);
    }
}

3. JSON序列化

3.1 System.Text.Json

using System.Text.Json;
using System.Text.Json.Serialization;

// 数据模型
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
    public DateTime BirthDate { get; set; }
    public Address Address { get; set; }
    public List<string> Hobbies { get; set; }
    public Dictionary<string, object> Metadata { get; set; }
    
    public Person()
    {
        Hobbies = new List<string>();
        Metadata = new Dictionary<string, object>();
    }
}

public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

// 带属性的模型
public class Product
{
    [JsonPropertyName("product_id")]
    public int Id { get; set; }
    
    [JsonPropertyName("product_name")]
    public string Name { get; set; }
    
    [JsonPropertyName("unit_price")]
    public decimal Price { get; set; }
    
    [JsonIgnore]
    public string InternalCode { get; set; }
    
    [JsonPropertyName("created_at")]
    public DateTime CreatedAt { get; set; }
    
    [JsonPropertyName("is_available")]
    public bool IsAvailable { get; set; }
    
    [JsonPropertyName("tags")]
    public List<string> Tags { get; set; }
    
    public Product()
    {
        Tags = new List<string>();
    }
}

public class JsonSerializationDemo
{
    private static readonly string BaseDirectory = Path.Combine(Environment.CurrentDirectory, "JsonDemo");
    
    public static void DemonstrateBasicJsonSerialization()
    {
        Console.WriteLine("\n=== 基础JSON序列化演示 ===");
        
        Directory.CreateDirectory(BaseDirectory);
        
        // 创建测试数据
        var person = new Person
        {
            Id = 1,
            Name = "张三",
            Age = 30,
            Email = "zhangsan@example.com",
            BirthDate = new DateTime(1993, 5, 15),
            Address = new Address
            {
                Street = "中山路123号",
                City = "北京",
                State = "北京市",
                ZipCode = "100000",
                Country = "中国"
            },
            Hobbies = new List<string> { "阅读", "游泳", "编程" },
            Metadata = new Dictionary<string, object>
            {
                { "level", "高级" },
                { "score", 95.5 },
                { "active", true }
            }
        };
        
        // 序列化为JSON字符串
        Console.WriteLine("\n--- 序列化 ---");
        
        var jsonString = JsonSerializer.Serialize(person, new JsonSerializerOptions
        {
            WriteIndented = true,
            Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
        });
        
        Console.WriteLine($"JSON字符串:\n{jsonString}");
        
        // 保存到文件
        var jsonFile = Path.Combine(BaseDirectory, "person.json");
        File.WriteAllText(jsonFile, jsonString, Encoding.UTF8);
        Console.WriteLine($"\nJSON已保存到: {jsonFile}");
        
        // 从JSON字符串反序列化
        Console.WriteLine("\n--- 反序列化 ---");
        
        var deserializedPerson = JsonSerializer.Deserialize<Person>(jsonString);
        
        Console.WriteLine($"反序列化结果:");
        Console.WriteLine($"ID: {deserializedPerson.Id}");
        Console.WriteLine($"姓名: {deserializedPerson.Name}");
        Console.WriteLine($"年龄: {deserializedPerson.Age}");
        Console.WriteLine($"邮箱: {deserializedPerson.Email}");
        Console.WriteLine($"生日: {deserializedPerson.BirthDate:yyyy-MM-dd}");
        Console.WriteLine($"地址: {deserializedPerson.Address.City}, {deserializedPerson.Address.Country}");
        Console.WriteLine($"爱好: [{string.Join(", ", deserializedPerson.Hobbies)}]");
        Console.WriteLine($"元数据: {deserializedPerson.Metadata.Count}项");
        
        // 从文件反序列化
        Console.WriteLine("\n--- 从文件反序列化 ---");
        
        var fileContent = File.ReadAllText(jsonFile, Encoding.UTF8);
        var personFromFile = JsonSerializer.Deserialize<Person>(fileContent);
        Console.WriteLine($"从文件读取的姓名: {personFromFile.Name}");
        
        // 清理
        File.Delete(jsonFile);
    }
    
    public static void DemonstrateJsonAttributes()
    {
        Console.WriteLine("\n=== JSON属性演示 ===");
        
        var product = new Product
        {
            Id = 1001,
            Name = "智能手机",
            Price = 2999.99m,
            InternalCode = "INTERNAL_001", // 这个字段会被忽略
            CreatedAt = DateTime.Now,
            IsAvailable = true,
            Tags = new List<string> { "电子产品", "通讯设备", "智能设备" }
        };
        
        // 序列化
        var options = new JsonSerializerOptions
        {
            WriteIndented = true,
            Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
        };
        
        var json = JsonSerializer.Serialize(product, options);
        Console.WriteLine($"带属性的JSON序列化:\n{json}");
        
        // 反序列化
        var deserializedProduct = JsonSerializer.Deserialize<Product>(json, options);
        Console.WriteLine($"\n反序列化结果:");
        Console.WriteLine($"ID: {deserializedProduct.Id}");
        Console.WriteLine($"名称: {deserializedProduct.Name}");
        Console.WriteLine($"价格: {deserializedProduct.Price:C}");
        Console.WriteLine($"内部代码: {deserializedProduct.InternalCode ?? "null (被忽略)"}");
        Console.WriteLine($"创建时间: {deserializedProduct.CreatedAt}");
        Console.WriteLine($"可用性: {deserializedProduct.IsAvailable}");
        Console.WriteLine($"标签: [{string.Join(", ", deserializedProduct.Tags)}]");
    }
    
    public static void DemonstrateJsonOptions()
    {
        Console.WriteLine("\n=== JSON选项演示 ===");
        
        var data = new
        {
            Id = 1,
            Name = "测试产品",
            Price = 99.99,
            CreatedAt = DateTime.Now,
            IsActive = true,
            Tags = new[] { "tag1", "tag2", "tag3" },
            Metadata = new Dictionary<string, object>
            {
                { "category", "electronics" },
                { "rating", 4.5 },
                { "inStock", true }
            }
        };
        
        // 默认选项
        Console.WriteLine("\n--- 默认选项 ---");
        var defaultJson = JsonSerializer.Serialize(data);
        Console.WriteLine($"默认JSON: {defaultJson}");
        
        // 格式化选项
        Console.WriteLine("\n--- 格式化选项 ---");
        var formattedOptions = new JsonSerializerOptions
        {
            WriteIndented = true
        };
        var formattedJson = JsonSerializer.Serialize(data, formattedOptions);
        Console.WriteLine($"格式化JSON:\n{formattedJson}");
        
        // 驼峰命名选项
        Console.WriteLine("\n--- 驼峰命名选项 ---");
        var camelCaseOptions = new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            WriteIndented = true
        };
        var camelCaseJson = JsonSerializer.Serialize(data, camelCaseOptions);
        Console.WriteLine($"驼峰命名JSON:\n{camelCaseJson}");
        
        // 忽略null值选项
        Console.WriteLine("\n--- 忽略null值选项 ---");
        var dataWithNull = new
        {
            Id = 1,
            Name = "测试",
            Description = (string)null,
            Price = 99.99,
            Category = (string)null
        };
        
        var ignoreNullOptions = new JsonSerializerOptions
        {
            DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
            WriteIndented = true
        };
        var ignoreNullJson = JsonSerializer.Serialize(dataWithNull, ignoreNullOptions);
        Console.WriteLine($"忽略null值JSON:\n{ignoreNullJson}");
        
        // 自定义日期格式
        Console.WriteLine("\n--- 自定义转换器 ---");
        var customOptions = new JsonSerializerOptions
        {
            WriteIndented = true,
            Converters = { new CustomDateTimeConverter() }
        };
        var customJson = JsonSerializer.Serialize(data, customOptions);
        Console.WriteLine($"自定义日期格式JSON:\n{customJson}");
    }
    
    public static async Task DemonstrateAsyncJsonSerialization()
    {
        Console.WriteLine("\n=== 异步JSON序列化演示 ===");
        
        var people = Enumerable.Range(1, 1000).Select(i => new Person
        {
            Id = i,
            Name = $"用户{i}",
            Age = 20 + (i % 50),
            Email = $"user{i}@example.com",
            BirthDate = DateTime.Now.AddYears(-(20 + (i % 50))),
            Address = new Address
            {
                Street = $"街道{i}号",
                City = "北京",
                State = "北京市",
                ZipCode = "100000",
                Country = "中国"
            },
            Hobbies = new List<string> { "爱好1", "爱好2" }
        }).ToList();
        
        var asyncJsonFile = Path.Combine(BaseDirectory, "people_async.json");
        
        // 异步序列化到文件
        Console.WriteLine("\n--- 异步序列化到文件 ---");
        var stopwatch = System.Diagnostics.Stopwatch.StartNew();
        
        using (var fileStream = File.Create(asyncJsonFile))
        {
            await JsonSerializer.SerializeAsync(fileStream, people, new JsonSerializerOptions
            {
                WriteIndented = true,
                Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
            });
        }
        
        stopwatch.Stop();
        var fileSize = new FileInfo(asyncJsonFile).Length;
        Console.WriteLine($"异步序列化完成: {people.Count}个对象");
        Console.WriteLine($"文件大小: {fileSize:N0} 字节");
        Console.WriteLine($"耗时: {stopwatch.ElapsedMilliseconds} 毫秒");
        
        // 异步反序列化
        Console.WriteLine("\n--- 异步反序列化 ---");
        stopwatch.Restart();
        
        List<Person> deserializedPeople;
        using (var fileStream = File.OpenRead(asyncJsonFile))
        {
            deserializedPeople = await JsonSerializer.DeserializeAsync<List<Person>>(fileStream);
        }
        
        stopwatch.Stop();
        Console.WriteLine($"异步反序列化完成: {deserializedPeople.Count}个对象");
        Console.WriteLine($"耗时: {stopwatch.ElapsedMilliseconds} 毫秒");
        Console.WriteLine($"第一个用户: {deserializedPeople[0].Name}");
        Console.WriteLine($"最后一个用户: {deserializedPeople[^1].Name}");
        
        // 清理
        File.Delete(asyncJsonFile);
        Directory.Delete(BaseDirectory);
    }
}

// 自定义日期时间转换器
public class CustomDateTimeConverter : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateTime.ParseExact(reader.GetString(), "yyyy-MM-dd HH:mm:ss", null);
    }
    
    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
    }
}

4. 总结

本章详细介绍了C#中的文件I/O和序列化:

  1. 文件和目录操作:基础操作、高级功能、路径处理
  2. 流操作:FileStream、MemoryStream、压缩流、自定义流
  3. 文本和二进制读写:StreamReader/Writer、BinaryReader/Writer
  4. JSON序列化:System.Text.Json的使用和配置

关键要点: - 合理选择文件操作方法 - 正确使用using语句管理资源 - 理解流的概念 - 掌握JSON序列化的配置和优化 - 异步操作提高性能

5. XML序列化

5.1 基础XML序列化

using System.Xml.Serialization;
using System.Xml;

// XML序列化模型
[XmlRoot("Library")]
public class Library
{
    [XmlElement("Name")]
    public string Name { get; set; }
    
    [XmlElement("Location")]
    public string Location { get; set; }
    
    [XmlArray("Books")]
    [XmlArrayItem("Book")]
    public List<Book> Books { get; set; }
    
    [XmlArray("Authors")]
    [XmlArrayItem("Author")]
    public List<Author> Authors { get; set; }
    
    public Library()
    {
        Books = new List<Book>();
        Authors = new List<Author>();
    }
}

public class Book
{
    [XmlAttribute("id")]
    public int Id { get; set; }
    
    [XmlElement("Title")]
    public string Title { get; set; }
    
    [XmlElement("ISBN")]
    public string ISBN { get; set; }
    
    [XmlElement("PublishDate")]
    public DateTime PublishDate { get; set; }
    
    [XmlElement("Price")]
    public decimal Price { get; set; }
    
    [XmlElement("AuthorId")]
    public int AuthorId { get; set; }
    
    [XmlElement("Category")]
    public BookCategory Category { get; set; }
    
    [XmlIgnore]
    public string InternalNotes { get; set; }
}

public class Author
{
    [XmlAttribute("id")]
    public int Id { get; set; }
    
    [XmlElement("FirstName")]
    public string FirstName { get; set; }
    
    [XmlElement("LastName")]
    public string LastName { get; set; }
    
    [XmlElement("BirthDate")]
    public DateTime BirthDate { get; set; }
    
    [XmlElement("Nationality")]
    public string Nationality { get; set; }
}

public enum BookCategory
{
    Fiction,
    NonFiction,
    Science,
    Technology,
    History,
    Biography
}

public class XmlSerializationDemo
{
    private static readonly string BaseDirectory = Path.Combine(Environment.CurrentDirectory, "XmlDemo");
    
    public static void DemonstrateBasicXmlSerialization()
    {
        Console.WriteLine("\n=== 基础XML序列化演示 ===");
        
        Directory.CreateDirectory(BaseDirectory);
        
        // 创建测试数据
        var library = new Library
        {
            Name = "中央图书馆",
            Location = "北京市朝阳区",
            Authors = new List<Author>
            {
                new Author
                {
                    Id = 1,
                    FirstName = "金庸",
                    LastName = "",
                    BirthDate = new DateTime(1924, 3, 10),
                    Nationality = "中国"
                },
                new Author
                {
                    Id = 2,
                    FirstName = "J.K.",
                    LastName = "Rowling",
                    BirthDate = new DateTime(1965, 7, 31),
                    Nationality = "英国"
                }
            },
            Books = new List<Book>
            {
                new Book
                {
                    Id = 1,
                    Title = "射雕英雄传",
                    ISBN = "978-7-108-01234-5",
                    PublishDate = new DateTime(1957, 1, 1),
                    Price = 45.80m,
                    AuthorId = 1,
                    Category = BookCategory.Fiction,
                    InternalNotes = "经典武侠小说"
                },
                new Book
                {
                    Id = 2,
                    Title = "Harry Potter and the Philosopher's Stone",
                    ISBN = "978-0-7475-3269-9",
                    PublishDate = new DateTime(1997, 6, 26),
                    Price = 29.99m,
                    AuthorId = 2,
                    Category = BookCategory.Fiction
                }
            }
        };
        
        var xmlFile = Path.Combine(BaseDirectory, "library.xml");
        
        // XML序列化
        Console.WriteLine("\n--- XML序列化 ---");
        
        var serializer = new XmlSerializer(typeof(Library));
        
        using (var writer = new StreamWriter(xmlFile, false, Encoding.UTF8))
        {
            serializer.Serialize(writer, library);
        }
        
        Console.WriteLine($"XML已保存到: {xmlFile}");
        
        // 读取并显示XML内容
        var xmlContent = File.ReadAllText(xmlFile, Encoding.UTF8);
        Console.WriteLine($"\nXML内容:\n{xmlContent}");
        
        // XML反序列化
        Console.WriteLine("\n--- XML反序列化 ---");
        
        Library deserializedLibrary;
        using (var reader = new StreamReader(xmlFile, Encoding.UTF8))
        {
            deserializedLibrary = (Library)serializer.Deserialize(reader);
        }
        
        Console.WriteLine($"图书馆名称: {deserializedLibrary.Name}");
        Console.WriteLine($"位置: {deserializedLibrary.Location}");
        Console.WriteLine($"作者数量: {deserializedLibrary.Authors.Count}");
        Console.WriteLine($"图书数量: {deserializedLibrary.Books.Count}");
        
        Console.WriteLine("\n作者列表:");
        foreach (var author in deserializedLibrary.Authors)
        {
            Console.WriteLine($"  {author.Id}: {author.FirstName} {author.LastName} ({author.Nationality})");
        }
        
        Console.WriteLine("\n图书列表:");
        foreach (var book in deserializedLibrary.Books)
        {
            Console.WriteLine($"  {book.Id}: {book.Title} - {book.Price:C} ({book.Category})");
        }
        
        // 清理
        File.Delete(xmlFile);
    }
    
    public static void DemonstrateXmlSettings()
    {
        Console.WriteLine("\n=== XML设置演示 ===");
        
        var book = new Book
        {
            Id = 1,
            Title = "示例图书",
            ISBN = "978-1-234-56789-0",
            PublishDate = DateTime.Now,
            Price = 39.99m,
            AuthorId = 1,
            Category = BookCategory.Technology
        };
        
        // 默认XML序列化
        Console.WriteLine("\n--- 默认XML序列化 ---");
        var defaultSerializer = new XmlSerializer(typeof(Book));
        
        using var defaultStringWriter = new StringWriter();
        defaultSerializer.Serialize(defaultStringWriter, book);
        var defaultXml = defaultStringWriter.ToString();
        Console.WriteLine($"默认XML:\n{defaultXml}");
        
        // 自定义XML设置
        Console.WriteLine("\n--- 自定义XML设置 ---");
        
        var settings = new XmlWriterSettings
        {
            Indent = true,
            IndentChars = "  ",
            NewLineChars = "\n",
            Encoding = Encoding.UTF8,
            OmitXmlDeclaration = false
        };
        
        using var customStringWriter = new StringWriter();
        using var xmlWriter = XmlWriter.Create(customStringWriter, settings);
        
        defaultSerializer.Serialize(xmlWriter, book);
        var customXml = customStringWriter.ToString();
        Console.WriteLine($"自定义格式XML:\n{customXml}");
        
        // 无命名空间XML
        Console.WriteLine("\n--- 无命名空间XML ---");
        
        var namespaces = new XmlSerializerNamespaces();
        namespaces.Add("", "");
        
        using var noNamespaceStringWriter = new StringWriter();
        using var noNamespaceXmlWriter = XmlWriter.Create(noNamespaceStringWriter, settings);
        
        defaultSerializer.Serialize(noNamespaceXmlWriter, book, namespaces);
        var noNamespaceXml = noNamespaceStringWriter.ToString();
        Console.WriteLine($"无命名空间XML:\n{noNamespaceXml}");
     }
 }

6. 自定义序列化

6.1 实现ISerializable接口

using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Permissions;

[Serializable]
public class CustomSerializableClass : ISerializable
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime CreatedDate { get; set; }
    public List<string> Tags { get; set; }
    
    // 私有字段,不会被自动序列化
    private string _secretKey;
    
    public CustomSerializableClass()
    {
        Tags = new List<string>();
        _secretKey = Guid.NewGuid().ToString();
    }
    
    // 反序列化构造函数
    protected CustomSerializableClass(SerializationInfo info, StreamingContext context)
    {
        Id = info.GetInt32("Id");
        Name = info.GetString("Name");
        CreatedDate = info.GetDateTime("CreatedDate");
        Tags = (List<string>)info.GetValue("Tags", typeof(List<string>));
        _secretKey = info.GetString("SecretKey");
    }
    
    // 序列化方法
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("Id", Id);
        info.AddValue("Name", Name);
        info.AddValue("CreatedDate", CreatedDate);
        info.AddValue("Tags", Tags);
        info.AddValue("SecretKey", _secretKey);
    }
    
    public string GetSecretKey() => _secretKey;
    
    public override string ToString()
    {
        return $"Id: {Id}, Name: {Name}, Created: {CreatedDate:yyyy-MM-dd}, Tags: [{string.Join(", ", Tags)}], Secret: {_secretKey[..8]}...";
    }
}

public class CustomSerializationDemo
{
    private static readonly string BaseDirectory = Path.Combine(Environment.CurrentDirectory, "CustomSerializationDemo");
    
    public static void DemonstrateCustomSerialization()
    {
        Console.WriteLine("\n=== 自定义序列化演示 ===");
        
        Directory.CreateDirectory(BaseDirectory);
        
        // 创建测试对象
        var original = new CustomSerializableClass
        {
            Id = 1,
            Name = "测试对象",
            CreatedDate = DateTime.Now,
            Tags = new List<string> { "标签1", "标签2", "标签3" }
        };
        
        Console.WriteLine($"原始对象: {original}");
        
        var binaryFile = Path.Combine(BaseDirectory, "custom_object.dat");
        
        // 二进制序列化(注意:BinaryFormatter在.NET 5+中已过时)
        Console.WriteLine("\n--- 二进制序列化 ---");
        
        try
        {
            var formatter = new BinaryFormatter();
            
            using (var fileStream = new FileStream(binaryFile, FileMode.Create))
            {
                formatter.Serialize(fileStream, original);
            }
            
            Console.WriteLine($"对象已序列化到: {binaryFile}");
            
            // 反序列化
            CustomSerializableClass deserialized;
            using (var fileStream = new FileStream(binaryFile, FileMode.Open))
            {
                deserialized = (CustomSerializableClass)formatter.Deserialize(fileStream);
            }
            
            Console.WriteLine($"反序列化对象: {deserialized}");
            Console.WriteLine($"密钥匹配: {original.GetSecretKey() == deserialized.GetSecretKey()}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"二进制序列化错误: {ex.Message}");
            Console.WriteLine("注意: BinaryFormatter在.NET 5+中已被标记为过时");
        }
        
        // 清理
        if (File.Exists(binaryFile))
        {
            File.Delete(binaryFile);
        }
        Directory.Delete(BaseDirectory);
    }
}

6.2 自定义JSON转换器

public class EncryptedString
{
    public string Value { get; set; }
    public bool IsEncrypted { get; set; }
    
    public EncryptedString(string value, bool isEncrypted = false)
    {
        Value = value;
        IsEncrypted = isEncrypted;
    }
}

public class EncryptedStringConverter : JsonConverter<EncryptedString>
{
    private const string EncryptionKey = "MySecretKey123456"; // 实际应用中应使用安全的密钥管理
    
    public override EncryptedString Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var jsonObject = JsonDocument.ParseValue(ref reader).RootElement;
        
        var value = jsonObject.GetProperty("value").GetString();
        var isEncrypted = jsonObject.GetProperty("isEncrypted").GetBoolean();
        
        if (isEncrypted)
        {
            value = Decrypt(value);
        }
        
        return new EncryptedString(value, false); // 解密后标记为未加密
    }
    
    public override void Write(Utf8JsonWriter writer, EncryptedString value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        
        if (value.IsEncrypted)
        {
            writer.WriteString("value", Encrypt(value.Value));
            writer.WriteBoolean("isEncrypted", true);
        }
        else
        {
            writer.WriteString("value", value.Value);
            writer.WriteBoolean("isEncrypted", false);
        }
        
        writer.WriteEndObject();
    }
    
    private string Encrypt(string plainText)
    {
        // 简单的Base64编码(实际应用中应使用真正的加密算法)
        var bytes = Encoding.UTF8.GetBytes(plainText + EncryptionKey);
        return Convert.ToBase64String(bytes);
    }
    
    private string Decrypt(string encryptedText)
    {
        // 简单的Base64解码
        var bytes = Convert.FromBase64String(encryptedText);
        var decrypted = Encoding.UTF8.GetString(bytes);
        return decrypted.Replace(EncryptionKey, "");
    }
}

public class SecureDocument
{
    public int Id { get; set; }
    public string Title { get; set; }
    public EncryptedString Content { get; set; }
    public DateTime CreatedAt { get; set; }
}

public class CustomJsonConverterDemo
{
    public static void DemonstrateCustomJsonConverter()
    {
        Console.WriteLine("\n=== 自定义JSON转换器演示 ===");
        
        var document = new SecureDocument
        {
            Id = 1,
            Title = "机密文档",
            Content = new EncryptedString("这是机密内容,需要加密存储", true),
            CreatedAt = DateTime.Now
        };
        
        var options = new JsonSerializerOptions
        {
            WriteIndented = true,
            Converters = { new EncryptedStringConverter() },
            Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
        };
        
        // 序列化(加密)
        Console.WriteLine("\n--- 序列化(加密) ---");
        var json = JsonSerializer.Serialize(document, options);
        Console.WriteLine($"序列化JSON:\n{json}");
        
        // 反序列化(解密)
        Console.WriteLine("\n--- 反序列化(解密) ---");
        var deserializedDocument = JsonSerializer.Deserialize<SecureDocument>(json, options);
        
        Console.WriteLine($"文档ID: {deserializedDocument.Id}");
        Console.WriteLine($"标题: {deserializedDocument.Title}");
        Console.WriteLine($"内容: {deserializedDocument.Content.Value}");
        Console.WriteLine($"是否加密: {deserializedDocument.Content.IsEncrypted}");
        Console.WriteLine($"创建时间: {deserializedDocument.CreatedAt}");
    }
}

7. 异步文件操作

7.1 异步文件读写

public class AsyncFileOperationsDemo
{
    private static readonly string BaseDirectory = Path.Combine(Environment.CurrentDirectory, "AsyncFileDemo");
    
    public static async Task DemonstrateAsyncFileOperations()
    {
        Console.WriteLine("\n=== 异步文件操作演示 ===");
        
        Directory.CreateDirectory(BaseDirectory);
        
        var asyncFile = Path.Combine(BaseDirectory, "async_demo.txt");
        
        // 异步写入文本
        Console.WriteLine("\n--- 异步写入文本 ---");
        var stopwatch = System.Diagnostics.Stopwatch.StartNew();
        
        var lines = Enumerable.Range(1, 10000)
            .Select(i => $"这是第 {i} 行异步写入的文本内容")
            .ToArray();
        
        await File.WriteAllLinesAsync(asyncFile, lines, Encoding.UTF8);
        
        stopwatch.Stop();
        Console.WriteLine($"异步写入完成: {lines.Length}行");
        Console.WriteLine($"耗时: {stopwatch.ElapsedMilliseconds} 毫秒");
        
        var fileSize = new FileInfo(asyncFile).Length;
        Console.WriteLine($"文件大小: {fileSize:N0} 字节");
        
        // 异步读取文本
        Console.WriteLine("\n--- 异步读取文本 ---");
        stopwatch.Restart();
        
        var readLines = await File.ReadAllLinesAsync(asyncFile, Encoding.UTF8);
        
        stopwatch.Stop();
        Console.WriteLine($"异步读取完成: {readLines.Length}行");
        Console.WriteLine($"耗时: {stopwatch.ElapsedMilliseconds} 毫秒");
        Console.WriteLine($"第一行: {readLines[0]}");
        Console.WriteLine($"最后一行: {readLines[^1]}");
        
        // 异步追加文本
        Console.WriteLine("\n--- 异步追加文本 ---");
        var appendLines = new[]
        {
            "\n=== 追加内容 ===",
            $"追加时间: {DateTime.Now}",
            "这是追加的第一行",
            "这是追加的第二行"
        };
        
        await File.AppendAllLinesAsync(asyncFile, appendLines, Encoding.UTF8);
        Console.WriteLine("异步追加完成");
        
        // 验证追加结果
        var finalContent = await File.ReadAllTextAsync(asyncFile, Encoding.UTF8);
        var finalLines = finalContent.Split('\n');
        Console.WriteLine($"最终行数: {finalLines.Length}");
        
        // 清理
        File.Delete(asyncFile);
    }
    
    public static async Task DemonstrateAsyncStreamOperations()
    {
        Console.WriteLine("\n=== 异步流操作演示 ===");
        
        var streamFile = Path.Combine(BaseDirectory, "async_stream.txt");
        
        // 异步流写入
        Console.WriteLine("\n--- 异步流写入 ---");
        
        using (var fileStream = new FileStream(streamFile, FileMode.Create, FileAccess.Write, FileShare.None, 4096, useAsync: true))
        using (var writer = new StreamWriter(fileStream, Encoding.UTF8))
        {
            for (int i = 1; i <= 5000; i++)
            {
                await writer.WriteLineAsync($"异步流写入第 {i} 行数据");
                
                if (i % 1000 == 0)
                {
                    await writer.FlushAsync();
                    Console.WriteLine($"已写入 {i} 行");
                }
            }
        }
        
        Console.WriteLine("异步流写入完成");
        
        // 异步流读取
        Console.WriteLine("\n--- 异步流读取 ---");
        
        var lineCount = 0;
        using (var fileStream = new FileStream(streamFile, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, useAsync: true))
        using (var reader = new StreamReader(fileStream, Encoding.UTF8))
        {
            string line;
            while ((line = await reader.ReadLineAsync()) != null)
            {
                lineCount++;
                
                if (lineCount % 1000 == 0)
                {
                    Console.WriteLine($"已读取 {lineCount} 行");
                }
            }
        }
        
        Console.WriteLine($"异步流读取完成: 总计 {lineCount} 行");
        
        // 清理
        File.Delete(streamFile);
    }
    
    public static async Task DemonstrateParallelFileProcessing()
    {
        Console.WriteLine("\n=== 并行文件处理演示 ===");
        
        // 创建多个测试文件
        var fileCount = 10;
        var files = new List<string>();
        
        Console.WriteLine($"\n--- 创建 {fileCount} 个测试文件 ---");
        
        var createTasks = Enumerable.Range(1, fileCount).Select(async i =>
        {
            var fileName = Path.Combine(BaseDirectory, $"parallel_file_{i}.txt");
            var content = Enumerable.Range(1, 1000)
                .Select(j => $"文件{i} - 第{j}行内容")
                .ToArray();
            
            await File.WriteAllLinesAsync(fileName, content, Encoding.UTF8);
            return fileName;
        });
        
        files.AddRange(await Task.WhenAll(createTasks));
        Console.WriteLine($"创建完成: {files.Count} 个文件");
        
        // 并行处理文件
        Console.WriteLine("\n--- 并行处理文件 ---");
        var stopwatch = System.Diagnostics.Stopwatch.StartNew();
        
        var processTasks = files.Select(async file =>
        {
            var lines = await File.ReadAllLinesAsync(file, Encoding.UTF8);
            var wordCount = lines.Sum(line => line.Split(' ').Length);
            var charCount = lines.Sum(line => line.Length);
            
            return new
            {
                FileName = Path.GetFileName(file),
                LineCount = lines.Length,
                WordCount = wordCount,
                CharCount = charCount
            };
        });
        
        var results = await Task.WhenAll(processTasks);
        stopwatch.Stop();
        
        Console.WriteLine($"并行处理完成,耗时: {stopwatch.ElapsedMilliseconds} 毫秒");
        Console.WriteLine("\n处理结果:");
        
        foreach (var result in results)
        {
            Console.WriteLine($"  {result.FileName}: {result.LineCount}行, {result.WordCount}词, {result.CharCount}字符");
        }
        
        var totalLines = results.Sum(r => r.LineCount);
        var totalWords = results.Sum(r => r.WordCount);
        var totalChars = results.Sum(r => r.CharCount);
        
        Console.WriteLine($"\n总计: {totalLines}行, {totalWords}词, {totalChars}字符");
        
        // 清理
        foreach (var file in files)
        {
            File.Delete(file);
        }
        
        Directory.Delete(BaseDirectory);
    }
}