学习目标
通过本章学习,你将掌握: - 文件和目录操作的基本方法 - 流(Stream)的概念和使用 - 文本文件的读写操作 - 二进制文件的处理 - 对象序列化和反序列化 - JSON、XML等数据格式的处理 - 异步文件操作 - 文件监控和事件处理
1. 文件和目录操作基础
1.1 File和Directory类
using System;
using System.IO;
using System.Linq;
public class FileDirectoryBasics
{
public static void DemonstrateFileDirectoryOperations()
{
Console.WriteLine("\n=== 文件和目录操作演示 ===");
Console.WriteLine("\n--- 目录操作 ---");
DirectoryOperations();
Console.WriteLine("\n--- 文件操作 ---");
FileOperations();
Console.WriteLine("\n--- 路径操作 ---");
PathOperations();
Console.WriteLine("\n--- 文件信息获取 ---");
FileInfoOperations();
}
private static void DirectoryOperations()
{
string testDir = Path.Combine(Path.GetTempPath(), "TestDirectory");
string subDir = Path.Combine(testDir, "SubDirectory");
try
{
// 创建目录
if (!Directory.Exists(testDir))
{
Directory.CreateDirectory(testDir);
Console.WriteLine($"创建目录: {testDir}");
}
// 创建子目录
Directory.CreateDirectory(subDir);
Console.WriteLine($"创建子目录: {subDir}");
// 获取目录信息
var dirInfo = new DirectoryInfo(testDir);
Console.WriteLine($"目录名称: {dirInfo.Name}");
Console.WriteLine($"完整路径: {dirInfo.FullName}");
Console.WriteLine($"创建时间: {dirInfo.CreationTime}");
Console.WriteLine($"最后访问时间: {dirInfo.LastAccessTime}");
// 列出目录内容
Console.WriteLine("\n目录内容:");
foreach (var dir in Directory.GetDirectories(testDir))
{
Console.WriteLine($" 目录: {Path.GetFileName(dir)}");
}
// 创建一些测试文件
for (int i = 1; i <= 3; i++)
{
string fileName = Path.Combine(testDir, $"test{i}.txt");
File.WriteAllText(fileName, $"这是测试文件 {i}");
}
foreach (var file in Directory.GetFiles(testDir))
{
Console.WriteLine($" 文件: {Path.GetFileName(file)}");
}
// 递归获取所有文件
Console.WriteLine("\n递归获取所有文件:");
var allFiles = Directory.GetFiles(testDir, "*.*", SearchOption.AllDirectories);
foreach (var file in allFiles)
{
Console.WriteLine($" {file}");
}
// 使用模式匹配
Console.WriteLine("\n.txt文件:");
var txtFiles = Directory.GetFiles(testDir, "*.txt", SearchOption.AllDirectories);
foreach (var file in txtFiles)
{
Console.WriteLine($" {Path.GetFileName(file)}");
}
}
finally
{
// 清理测试目录
if (Directory.Exists(testDir))
{
Directory.Delete(testDir, true);
Console.WriteLine($"\n删除测试目录: {testDir}");
}
}
}
private static void FileOperations()
{
string testFile = Path.Combine(Path.GetTempPath(), "test.txt");
try
{
// 创建文件
File.WriteAllText(testFile, "Hello, World!");
Console.WriteLine($"创建文件: {testFile}");
// 检查文件是否存在
if (File.Exists(testFile))
{
Console.WriteLine("文件存在");
// 读取文件内容
string content = File.ReadAllText(testFile);
Console.WriteLine($"文件内容: {content}");
// 追加内容
File.AppendAllText(testFile, "\n追加的内容");
// 再次读取
content = File.ReadAllText(testFile);
Console.WriteLine($"追加后内容: {content}");
// 获取文件属性
var attributes = File.GetAttributes(testFile);
Console.WriteLine($"文件属性: {attributes}");
// 获取文件时间信息
Console.WriteLine($"创建时间: {File.GetCreationTime(testFile)}");
Console.WriteLine($"最后写入时间: {File.GetLastWriteTime(testFile)}");
Console.WriteLine($"最后访问时间: {File.GetLastAccessTime(testFile)}");
}
// 复制文件
string copyFile = Path.Combine(Path.GetTempPath(), "test_copy.txt");
File.Copy(testFile, copyFile, true);
Console.WriteLine($"复制文件到: {copyFile}");
// 移动文件
string moveFile = Path.Combine(Path.GetTempPath(), "test_moved.txt");
File.Move(copyFile, moveFile);
Console.WriteLine($"移动文件到: {moveFile}");
// 删除文件
File.Delete(moveFile);
Console.WriteLine($"删除文件: {moveFile}");
}
finally
{
// 清理
if (File.Exists(testFile))
{
File.Delete(testFile);
}
}
}
private static void PathOperations()
{
string filePath = @"C:\Users\Username\Documents\test.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)}");
// 路径组合
string combinedPath = Path.Combine("C:", "Users", "Username", "Documents", "test.txt");
Console.WriteLine($"组合路径: {combinedPath}");
// 获取临时路径
Console.WriteLine($"临时目录: {Path.GetTempPath()}");
Console.WriteLine($"临时文件名: {Path.GetTempFileName()}");
// 路径验证
Console.WriteLine($"是否为绝对路径: {Path.IsPathRooted(filePath)}");
// 获取相对路径
string relativePath = Path.GetRelativePath(@"C:\Users", filePath);
Console.WriteLine($"相对路径: {relativePath}");
// 获取完整路径
string fullPath = Path.GetFullPath("test.txt");
Console.WriteLine($"完整路径: {fullPath}");
}
private static void FileInfoOperations()
{
string testFile = Path.Combine(Path.GetTempPath(), "fileinfo_test.txt");
try
{
// 创建测试文件
File.WriteAllText(testFile, "FileInfo测试内容\n这是第二行");
var fileInfo = new FileInfo(testFile);
Console.WriteLine($"文件名: {fileInfo.Name}");
Console.WriteLine($"完整路径: {fileInfo.FullName}");
Console.WriteLine($"目录: {fileInfo.DirectoryName}");
Console.WriteLine($"大小: {fileInfo.Length} 字节");
Console.WriteLine($"创建时间: {fileInfo.CreationTime}");
Console.WriteLine($"最后修改时间: {fileInfo.LastWriteTime}");
Console.WriteLine($"最后访问时间: {fileInfo.LastAccessTime}");
Console.WriteLine($"属性: {fileInfo.Attributes}");
Console.WriteLine($"是否只读: {fileInfo.IsReadOnly}");
Console.WriteLine($"是否存在: {fileInfo.Exists}");
// 使用FileInfo进行操作
var copyInfo = fileInfo.CopyTo(Path.Combine(Path.GetTempPath(), "fileinfo_copy.txt"), true);
Console.WriteLine($"复制到: {copyInfo.FullName}");
// 清理
copyInfo.Delete();
}
finally
{
if (File.Exists(testFile))
{
File.Delete(testFile);
}
}
}
}
实践练习
练习1:配置管理系统
using System;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
// 配置数据模型
public class ApplicationConfig
{
public DatabaseConfig Database { get; set; } = new();
public LoggingConfig Logging { get; set; } = new();
public ApiConfig Api { get; set; } = new();
public Dictionary<string, object> CustomSettings { get; set; } = new();
}
public class DatabaseConfig
{
public string ConnectionString { get; set; } = "";
public int MaxConnections { get; set; } = 100;
public TimeSpan CommandTimeout { get; set; } = TimeSpan.FromSeconds(30);
}
public class LoggingConfig
{
public string Level { get; set; } = "Information";
public string FilePath { get; set; } = "logs/app.log";
public long MaxFileSize { get; set; } = 10 * 1024 * 1024; // 10MB
}
public class ApiConfig
{
public string BaseUrl { get; set; } = "https://api.example.com";
public string ApiKey { get; set; } = "";
public TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds(30);
}
// 配置管理器
public class ConfigurationManager
{
private readonly string _configPath;
private readonly JsonSerializerOptions _jsonOptions;
private ApplicationConfig _config;
private readonly FileSystemWatcher _watcher;
public event Action<ApplicationConfig> ConfigChanged;
public ConfigurationManager(string configPath = "appsettings.json")
{
_configPath = configPath;
_jsonOptions = new JsonSerializerOptions
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Converters = { new JsonStringEnumConverter(), new TimeSpanJsonConverter() }
};
// 监听配置文件变化
_watcher = new FileSystemWatcher(Path.GetDirectoryName(_configPath) ?? ".", Path.GetFileName(_configPath));
_watcher.Changed += OnConfigFileChanged;
_watcher.EnableRaisingEvents = true;
}
public async Task<ApplicationConfig> LoadConfigAsync()
{
if (!File.Exists(_configPath))
{
_config = new ApplicationConfig();
await SaveConfigAsync(_config);
return _config;
}
var json = await File.ReadAllTextAsync(_configPath);
_config = JsonSerializer.Deserialize<ApplicationConfig>(json, _jsonOptions);
return _config;
}
public async Task SaveConfigAsync(ApplicationConfig config)
{
_config = config;
var json = JsonSerializer.Serialize(config, _jsonOptions);
await FileOperationBestPractices.SafeWriteAllTextAsync(_configPath, json);
}
public T GetSection<T>(string sectionName) where T : new()
{
if (_config == null)
throw new InvalidOperationException("Configuration not loaded");
var property = typeof(ApplicationConfig).GetProperty(sectionName);
return property?.GetValue(_config) is T value ? value : new T();
}
private async void OnConfigFileChanged(object sender, FileSystemEventArgs e)
{
try
{
await Task.Delay(100); // 防止文件被锁定
var newConfig = await LoadConfigAsync();
ConfigChanged?.Invoke(newConfig);
}
catch (Exception ex)
{
Console.WriteLine($"Error reloading config: {ex.Message}");
}
}
public void Dispose()
{
_watcher?.Dispose();
}
}
// TimeSpan的JSON转换器
public class TimeSpanJsonConverter : JsonConverter<TimeSpan>
{
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return TimeSpan.Parse(reader.GetString());
}
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
练习2:数据备份和恢复系统
using System;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text.Json;
// 备份元数据
public class BackupMetadata
{
public string BackupId { get; set; } = Guid.NewGuid().ToString();
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public string Description { get; set; } = "";
public long OriginalSize { get; set; }
public long CompressedSize { get; set; }
public string CheckSum { get; set; } = "";
public List<string> Files { get; set; } = new();
}
// 备份系统
public class BackupSystem
{
private readonly string _backupDirectory;
public BackupSystem(string backupDirectory = "backups")
{
_backupDirectory = backupDirectory;
Directory.CreateDirectory(_backupDirectory);
}
// 创建备份
public async Task<string> CreateBackupAsync(string sourceDirectory, string description = "")
{
var backupId = Guid.NewGuid().ToString();
var backupPath = Path.Combine(_backupDirectory, $"{backupId}.zip");
var metadataPath = Path.Combine(_backupDirectory, $"{backupId}.metadata.json");
var metadata = new BackupMetadata
{
BackupId = backupId,
Description = description
};
// 计算原始大小
var files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories);
metadata.OriginalSize = files.Sum(f => new FileInfo(f).Length);
metadata.Files = files.Select(f => Path.GetRelativePath(sourceDirectory, f)).ToList();
// 创建压缩备份
using (var zipStream = new FileStream(backupPath, FileMode.Create))
using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create))
{
foreach (var file in files)
{
var relativePath = Path.GetRelativePath(sourceDirectory, file);
var entry = archive.CreateEntry(relativePath);
using var entryStream = entry.Open();
using var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
await fileStream.CopyToAsync(entryStream);
}
}
// 计算压缩后大小和校验和
var backupInfo = new FileInfo(backupPath);
metadata.CompressedSize = backupInfo.Length;
metadata.CheckSum = await ComputeFileHashAsync(backupPath);
// 保存元数据
var metadataJson = JsonSerializer.Serialize(metadata, new JsonSerializerOptions { WriteIndented = true });
await File.WriteAllTextAsync(metadataPath, metadataJson);
return backupId;
}
// 恢复备份
public async Task RestoreBackupAsync(string backupId, string targetDirectory)
{
var backupPath = Path.Combine(_backupDirectory, $"{backupId}.zip");
var metadataPath = Path.Combine(_backupDirectory, $"{backupId}.metadata.json");
if (!File.Exists(backupPath) || !File.Exists(metadataPath))
throw new FileNotFoundException($"Backup {backupId} not found");
// 验证备份完整性
var metadataJson = await File.ReadAllTextAsync(metadataPath);
var metadata = JsonSerializer.Deserialize<BackupMetadata>(metadataJson);
var currentHash = await ComputeFileHashAsync(backupPath);
if (currentHash != metadata.CheckSum)
throw new InvalidDataException("Backup file is corrupted");
// 创建目标目录
Directory.CreateDirectory(targetDirectory);
// 解压备份
using var zipStream = new FileStream(backupPath, FileMode.Open, FileAccess.Read);
using var archive = new ZipArchive(zipStream, ZipArchiveMode.Read);
foreach (var entry in archive.Entries)
{
var targetPath = Path.Combine(targetDirectory, entry.FullName);
var targetDir = Path.GetDirectoryName(targetPath);
if (!string.IsNullOrEmpty(targetDir))
Directory.CreateDirectory(targetDir);
using var entryStream = entry.Open();
using var targetStream = new FileStream(targetPath, FileMode.Create);
await entryStream.CopyToAsync(targetStream);
}
}
// 列出所有备份
public async Task<List<BackupMetadata>> ListBackupsAsync()
{
var backups = new List<BackupMetadata>();
var metadataFiles = Directory.GetFiles(_backupDirectory, "*.metadata.json");
foreach (var file in metadataFiles)
{
try
{
var json = await File.ReadAllTextAsync(file);
var metadata = JsonSerializer.Deserialize<BackupMetadata>(json);
backups.Add(metadata);
}
catch (Exception ex)
{
Console.WriteLine($"Error reading metadata {file}: {ex.Message}");
}
}
return backups.OrderByDescending(b => b.CreatedAt).ToList();
}
// 删除备份
public async Task DeleteBackupAsync(string backupId)
{
var backupPath = Path.Combine(_backupDirectory, $"{backupId}.zip");
var metadataPath = Path.Combine(_backupDirectory, $"{backupId}.metadata.json");
if (File.Exists(backupPath))
File.Delete(backupPath);
if (File.Exists(metadataPath))
File.Delete(metadataPath);
}
// 计算文件哈希
private async Task<string> ComputeFileHashAsync(string filePath)
{
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
using var sha256 = SHA256.Create();
var hash = await sha256.ComputeHashAsync(stream);
return Convert.ToHexString(hash);
}
}
// 使用示例
public class BackupDemo
{
public static async Task DemoBackupSystem()
{
var backupSystem = new BackupSystem();
// 创建备份
var backupId = await backupSystem.CreateBackupAsync(
@"C:\MyProject",
"Project backup before major refactoring");
Console.WriteLine($"Backup created: {backupId}");
// 列出备份
var backups = await backupSystem.ListBackupsAsync();
foreach (var backup in backups)
{
Console.WriteLine($"Backup: {backup.BackupId}");
Console.WriteLine($" Created: {backup.CreatedAt}");
Console.WriteLine($" Description: {backup.Description}");
Console.WriteLine($" Size: {backup.OriginalSize:N0} -> {backup.CompressedSize:N0} bytes");
Console.WriteLine($" Compression: {(1 - (double)backup.CompressedSize / backup.OriginalSize):P1}");
}
// 恢复备份
await backupSystem.RestoreBackupAsync(backupId, @"C:\RestoredProject");
Console.WriteLine("Backup restored successfully");
}
}
本章总结
在本章中,我们深入学习了C#中的文件I/O和序列化技术:
核心概念
- 文件和目录操作:掌握了File、Directory、Path、FileInfo等类的使用
- 流操作:理解了FileStream、MemoryStream、BufferedStream的特点和应用场景
- 文本读写:学会了StreamWriter/Reader、StringWriter/Reader的使用和编码处理
- 二进制文件:掌握了BinaryWriter/Reader进行二进制数据读写
序列化技术
- JSON序列化:学习了System.Text.Json和Newtonsoft.Json的使用
- XML序列化:掌握了XmlSerializer的基本和高级用法
- 二进制序列化:了解了现代二进制序列化方案如MessagePack
- 自定义序列化:学会了创建自定义转换器和控制序列化行为
高级技术
- 流式序列化:掌握了处理大量数据的流式读写技术
- 性能优化:学习了ArrayPool、预编译序列化器等优化技术
- 最佳实践:掌握了安全文件操作、错误处理、并发控制等实践
实际应用
- 配置管理系统:实现了完整的配置文件管理和监听机制
- 备份恢复系统:构建了具有压缩、校验、元数据管理的备份系统
重要技能
- 选择合适的I/O类和序列化方案
- 处理大文件和流式数据
- 实现高性能的文件操作
- 设计健壮的错误处理机制
- 应用安全的文件操作模式
文件I/O和序列化是应用程序与外部数据交互的基础,掌握这些技术对于构建实用的应用程序至关重要。
下一章预告:第17章将介绍网络编程,包括HTTP客户端、TCP/UDP通信、WebSocket等网络通信技术。
1.2 DriveInfo和磁盘信息
public class DriveInfoDemo
{
public static void DemonstrateDriveInfo()
{
Console.WriteLine("\n=== 磁盘信息演示 ===");
// 获取所有驱动器
DriveInfo[] drives = DriveInfo.GetDrives();
Console.WriteLine($"系统中共有 {drives.Length} 个驱动器:");
foreach (DriveInfo drive in drives)
{
Console.WriteLine($"\n驱动器: {drive.Name}");
Console.WriteLine($"类型: {drive.DriveType}");
if (drive.IsReady)
{
Console.WriteLine($"标签: {drive.VolumeLabel}");
Console.WriteLine($"文件系统: {drive.DriveFormat}");
Console.WriteLine($"总大小: {FormatBytes(drive.TotalSize)}");
Console.WriteLine($"可用空间: {FormatBytes(drive.AvailableFreeSpace)}");
Console.WriteLine($"空闲空间: {FormatBytes(drive.TotalFreeSpace)}");
double usedPercentage = (double)(drive.TotalSize - drive.TotalFreeSpace) / drive.TotalSize * 100;
Console.WriteLine($"使用率: {usedPercentage:F2}%");
// 根目录信息
var rootDir = drive.RootDirectory;
Console.WriteLine($"根目录: {rootDir.FullName}");
try
{
var subDirs = rootDir.GetDirectories().Take(5);
Console.WriteLine("根目录下的前5个子目录:");
foreach (var dir in subDirs)
{
Console.WriteLine($" {dir.Name}");
}
}
catch (UnauthorizedAccessException)
{
Console.WriteLine(" 无权限访问根目录内容");
}
}
else
{
Console.WriteLine("驱动器未就绪");
}
}
// 获取特定驱动器信息
Console.WriteLine("\n--- 当前目录所在驱动器信息 ---");
string currentDrive = Path.GetPathRoot(Environment.CurrentDirectory);
DriveInfo currentDriveInfo = new DriveInfo(currentDrive);
if (currentDriveInfo.IsReady)
{
Console.WriteLine($"当前驱动器: {currentDriveInfo.Name}");
Console.WriteLine($"可用空间: {FormatBytes(currentDriveInfo.AvailableFreeSpace)}");
Console.WriteLine($"总空间: {FormatBytes(currentDriveInfo.TotalSize)}");
// 检查磁盘空间是否充足
long requiredSpace = 1024 * 1024 * 100; // 100MB
bool hasEnoughSpace = currentDriveInfo.AvailableFreeSpace > requiredSpace;
Console.WriteLine($"是否有足够空间(100MB): {hasEnoughSpace}");
}
}
private static string FormatBytes(long bytes)
{
string[] suffixes = { "B", "KB", "MB", "GB", "TB", "PB" };
int counter = 0;
decimal number = bytes;
while (Math.Round(number / 1024) >= 1)
{
number /= 1024;
counter++;
}
return $"{number:N2} {suffixes[counter]}";
}
}
2. 流(Stream)操作
2.1 Stream基础概念
using System.Text;
public class StreamBasics
{
public static void DemonstrateStreamOperations()
{
Console.WriteLine("\n=== 流操作演示 ===");
Console.WriteLine("\n--- FileStream操作 ---");
FileStreamOperations();
Console.WriteLine("\n--- MemoryStream操作 ---");
MemoryStreamOperations();
Console.WriteLine("\n--- BufferedStream操作 ---");
BufferedStreamOperations();
Console.WriteLine("\n--- 流的复制和转换 ---");
StreamCopyAndConversion();
}
private static void FileStreamOperations()
{
string testFile = Path.Combine(Path.GetTempPath(), "stream_test.txt");
try
{
// 写入数据到文件流
using (var fileStream = new FileStream(testFile, FileMode.Create, FileAccess.Write))
{
string text = "Hello, FileStream!\n这是中文测试";
byte[] data = Encoding.UTF8.GetBytes(text);
fileStream.Write(data, 0, data.Length);
Console.WriteLine($"写入 {data.Length} 字节到文件");
// 获取流信息
Console.WriteLine($"流位置: {fileStream.Position}");
Console.WriteLine($"流长度: {fileStream.Length}");
Console.WriteLine($"可读: {fileStream.CanRead}");
Console.WriteLine($"可写: {fileStream.CanWrite}");
Console.WriteLine($"可定位: {fileStream.CanSeek}");
}
// 从文件流读取数据
using (var fileStream = new FileStream(testFile, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[fileStream.Length];
int bytesRead = fileStream.Read(buffer, 0, buffer.Length);
string text = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine($"读取 {bytesRead} 字节: {text}");
// 流定位操作
fileStream.Seek(0, SeekOrigin.Begin);
Console.WriteLine($"重置到开始位置: {fileStream.Position}");
// 读取前5个字节
byte[] firstBytes = new byte[5];
fileStream.Read(firstBytes, 0, 5);
string firstText = Encoding.UTF8.GetString(firstBytes);
Console.WriteLine($"前5个字节: {firstText}");
}
}
finally
{
if (File.Exists(testFile))
{
File.Delete(testFile);
}
}
}
private static void MemoryStreamOperations()
{
// 创建内存流
using (var memoryStream = new MemoryStream())
{
// 写入数据
string text = "MemoryStream测试数据";
byte[] data = Encoding.UTF8.GetBytes(text);
memoryStream.Write(data, 0, data.Length);
Console.WriteLine($"写入 {data.Length} 字节到内存流");
// 获取内存流的字节数组
byte[] streamData = memoryStream.ToArray();
Console.WriteLine($"内存流数据: {Encoding.UTF8.GetString(streamData)}");
// 重置位置并读取
memoryStream.Seek(0, SeekOrigin.Begin);
byte[] readBuffer = new byte[memoryStream.Length];
int bytesRead = memoryStream.Read(readBuffer, 0, readBuffer.Length);
Console.WriteLine($"读取 {bytesRead} 字节: {Encoding.UTF8.GetString(readBuffer)}");
// 追加数据
memoryStream.Seek(0, SeekOrigin.End);
string appendText = "\n追加的数据";
byte[] appendData = Encoding.UTF8.GetBytes(appendText);
memoryStream.Write(appendData, 0, appendData.Length);
Console.WriteLine($"追加后的数据: {Encoding.UTF8.GetString(memoryStream.ToArray())}");
}
// 从字节数组创建内存流
byte[] initialData = Encoding.UTF8.GetBytes("初始数据");
using (var memoryStream = new MemoryStream(initialData))
{
Console.WriteLine($"\n从字节数组创建的内存流长度: {memoryStream.Length}");
// 读取数据
memoryStream.Seek(0, SeekOrigin.Begin);
byte[] buffer = new byte[memoryStream.Length];
memoryStream.Read(buffer, 0, buffer.Length);
Console.WriteLine($"读取的数据: {Encoding.UTF8.GetString(buffer)}");
}
}
private static void BufferedStreamOperations()
{
string testFile = Path.Combine(Path.GetTempPath(), "buffered_test.txt");
try
{
// 使用缓冲流写入
using (var fileStream = new FileStream(testFile, FileMode.Create))
using (var bufferedStream = new BufferedStream(fileStream, 4096))
{
for (int i = 0; i < 1000; i++)
{
string line = $"这是第 {i + 1} 行数据\n";
byte[] data = Encoding.UTF8.GetBytes(line);
bufferedStream.Write(data, 0, data.Length);
}
// 强制刷新缓冲区
bufferedStream.Flush();
Console.WriteLine("使用缓冲流写入1000行数据");
}
// 使用缓冲流读取
using (var fileStream = new FileStream(testFile, FileMode.Open))
using (var bufferedStream = new BufferedStream(fileStream, 4096))
{
byte[] buffer = new byte[1024];
int totalBytesRead = 0;
int bytesRead;
while ((bytesRead = bufferedStream.Read(buffer, 0, buffer.Length)) > 0)
{
totalBytesRead += bytesRead;
}
Console.WriteLine($"使用缓冲流读取了 {totalBytesRead} 字节");
}
// 性能对比
Console.WriteLine("\n性能对比:");
CompareStreamPerformance(testFile);
}
finally
{
if (File.Exists(testFile))
{
File.Delete(testFile);
}
}
}
private static void CompareStreamPerformance(string testFile)
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
// 直接使用FileStream
stopwatch.Restart();
using (var fileStream = new FileStream(testFile, FileMode.Open))
{
byte[] buffer = new byte[1];
while (fileStream.Read(buffer, 0, 1) > 0)
{
// 逐字节读取
}
}
stopwatch.Stop();
long directStreamTime = stopwatch.ElapsedMilliseconds;
// 使用BufferedStream
stopwatch.Restart();
using (var fileStream = new FileStream(testFile, FileMode.Open))
using (var bufferedStream = new BufferedStream(fileStream))
{
byte[] buffer = new byte[1];
while (bufferedStream.Read(buffer, 0, 1) > 0)
{
// 逐字节读取
}
}
stopwatch.Stop();
long bufferedStreamTime = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"直接FileStream时间: {directStreamTime}ms");
Console.WriteLine($"BufferedStream时间: {bufferedStreamTime}ms");
Console.WriteLine($"性能提升: {(double)directStreamTime / Math.Max(bufferedStreamTime, 1):F2}x");
}
private static void StreamCopyAndConversion()
{
// 流之间的复制
string sourceText = "这是要复制的数据\n包含多行内容\n用于测试流复制功能";
using (var sourceStream = new MemoryStream(Encoding.UTF8.GetBytes(sourceText)))
using (var destinationStream = new MemoryStream())
{
// 复制流
sourceStream.CopyTo(destinationStream);
Console.WriteLine($"源流长度: {sourceStream.Length}");
Console.WriteLine($"目标流长度: {destinationStream.Length}");
Console.WriteLine($"复制的数据: {Encoding.UTF8.GetString(destinationStream.ToArray())}");
}
// 使用缓冲区复制
using (var sourceStream = new MemoryStream(Encoding.UTF8.GetBytes(sourceText)))
using (var destinationStream = new MemoryStream())
{
byte[] buffer = new byte[1024];
int bytesRead;
int totalBytes = 0;
sourceStream.Seek(0, SeekOrigin.Begin);
while ((bytesRead = sourceStream.Read(buffer, 0, buffer.Length)) > 0)
{
destinationStream.Write(buffer, 0, bytesRead);
totalBytes += bytesRead;
}
Console.WriteLine($"\n手动复制了 {totalBytes} 字节");
Console.WriteLine($"复制结果: {Encoding.UTF8.GetString(destinationStream.ToArray())}");
}
}
}
2.2 文本读写器
public class TextReaderWriterDemo
{
public static void DemonstrateTextReaderWriter()
{
Console.WriteLine("\n=== 文本读写器演示 ===");
Console.WriteLine("\n--- StreamWriter和StreamReader ---");
StreamWriterReaderDemo();
Console.WriteLine("\n--- StringWriter和StringReader ---");
StringWriterReaderDemo();
Console.WriteLine("\n--- 编码处理 ---");
EncodingDemo();
Console.WriteLine("\n--- 大文件处理 ---");
LargeFileDemo();
}
private static void StreamWriterReaderDemo()
{
string testFile = Path.Combine(Path.GetTempPath(), "text_test.txt");
try
{
// 使用StreamWriter写入文本
using (var writer = new StreamWriter(testFile, false, Encoding.UTF8))
{
writer.WriteLine("第一行文本");
writer.WriteLine("第二行文本");
writer.Write("不换行的文本");
writer.Write(" 继续在同一行");
writer.WriteLine(); // 手动换行
writer.WriteLine($"当前时间: {DateTime.Now}");
// 写入格式化文本
writer.WriteLine("格式化文本: {0}, {1:F2}", "测试", 123.456);
// 自动刷新
writer.AutoFlush = true;
writer.WriteLine("自动刷新的文本");
}
Console.WriteLine($"文本已写入到: {testFile}");
// 使用StreamReader读取文本
using (var reader = new StreamReader(testFile, Encoding.UTF8))
{
Console.WriteLine("\n逐行读取:");
string line;
int lineNumber = 1;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine($"第{lineNumber}行: {line}");
lineNumber++;
}
}
// 一次性读取所有内容
using (var reader = new StreamReader(testFile, Encoding.UTF8))
{
string allContent = reader.ReadToEnd();
Console.WriteLine($"\n全部内容:\n{allContent}");
}
// 读取指定字符数
using (var reader = new StreamReader(testFile, Encoding.UTF8))
{
char[] buffer = new char[10];
int charsRead = reader.Read(buffer, 0, buffer.Length);
Console.WriteLine($"\n读取前{charsRead}个字符: {new string(buffer, 0, charsRead)}");
}
}
finally
{
if (File.Exists(testFile))
{
File.Delete(testFile);
}
}
}
private static void StringWriterReaderDemo()
{
// StringWriter示例
using (var stringWriter = new StringWriter())
{
stringWriter.WriteLine("使用StringWriter");
stringWriter.WriteLine("写入到内存中的字符串");
stringWriter.Write("数字: ");
stringWriter.WriteLine(42);
stringWriter.WriteLine($"时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
string result = stringWriter.ToString();
Console.WriteLine($"StringWriter结果:\n{result}");
}
// StringReader示例
string text = "第一行\n第二行\n第三行\n最后一行";
using (var stringReader = new StringReader(text))
{
Console.WriteLine("\nStringReader逐行读取:");
string line;
int lineNumber = 1;
while ((line = stringReader.ReadLine()) != null)
{
Console.WriteLine($"行{lineNumber}: {line}");
lineNumber++;
}
}
// 使用StringReader读取字符
using (var stringReader = new StringReader(text))
{
Console.WriteLine("\n逐字符读取前10个字符:");
for (int i = 0; i < 10; i++)
{
int ch = stringReader.Read();
if (ch == -1) break;
char character = (char)ch;
Console.Write(character == '\n' ? "\\n" : character.ToString());
}
Console.WriteLine();
}
}
private static void EncodingDemo()
{
string testFile = Path.Combine(Path.GetTempPath(), "encoding_test.txt");
string testText = "Hello World! 你好世界! こんにちは! 🌍";
try
{
// 测试不同编码
var encodings = new[]
{
new { Name = "UTF-8", Encoding = Encoding.UTF8 },
new { Name = "UTF-16", Encoding = Encoding.Unicode },
new { Name = "UTF-32", Encoding = Encoding.UTF32 },
new { Name = "ASCII", Encoding = Encoding.ASCII },
new { Name = "GBK", Encoding = Encoding.GetEncoding("GBK") }
};
foreach (var enc in encodings)
{
try
{
// 写入文件
using (var writer = new StreamWriter(testFile, false, enc.Encoding))
{
writer.WriteLine(testText);
}
// 读取文件
using (var reader = new StreamReader(testFile, enc.Encoding))
{
string readText = reader.ReadLine();
Console.WriteLine($"{enc.Name}: {readText}");
// 检查是否正确读取
bool isCorrect = readText == testText;
Console.WriteLine($" 编码正确: {isCorrect}");
}
// 显示文件大小
var fileInfo = new FileInfo(testFile);
Console.WriteLine($" 文件大小: {fileInfo.Length} 字节\n");
}
catch (Exception ex)
{
Console.WriteLine($"{enc.Name}: 编码错误 - {ex.Message}\n");
}
}
// 自动检测编码
Console.WriteLine("--- 自动检测编码 ---");
// 写入UTF-8文件(带BOM)
using (var writer = new StreamWriter(testFile, false, new UTF8Encoding(true)))
{
writer.WriteLine(testText);
}
// 自动检测编码读取
using (var reader = new StreamReader(testFile, true))
{
string content = reader.ReadLine();
Console.WriteLine($"自动检测编码: {reader.CurrentEncoding.EncodingName}");
Console.WriteLine($"读取内容: {content}");
}
}
finally
{
if (File.Exists(testFile))
{
File.Delete(testFile);
}
}
}
private static void LargeFileDemo()
{
string largeFile = Path.Combine(Path.GetTempPath(), "large_file.txt");
try
{
// 创建大文件
Console.WriteLine("创建大文件...");
using (var writer = new StreamWriter(largeFile))
{
for (int i = 1; i <= 100000; i++)
{
writer.WriteLine($"这是第 {i} 行,包含一些测试数据 - {DateTime.Now.Ticks}");
if (i % 10000 == 0)
{
Console.WriteLine($"已写入 {i} 行");
}
}
}
var fileInfo = new FileInfo(largeFile);
Console.WriteLine($"大文件创建完成,大小: {fileInfo.Length / 1024 / 1024:F2} MB");
// 高效读取大文件
Console.WriteLine("\n高效读取大文件前10行:");
using (var reader = new StreamReader(largeFile))
{
for (int i = 0; i < 10; i++)
{
string line = reader.ReadLine();
if (line == null) break;
Console.WriteLine($" {line}");
}
}
// 搜索特定内容
Console.WriteLine("\n搜索包含'50000'的行:");
using (var reader = new StreamReader(largeFile))
{
string line;
int lineNumber = 0;
while ((line = reader.ReadLine()) != null)
{
lineNumber++;
if (line.Contains("50000"))
{
Console.WriteLine($" 第{lineNumber}行: {line}");
break;
}
}
}
// 统计行数
Console.WriteLine("\n统计文件行数:");
int totalLines = 0;
using (var reader = new StreamReader(largeFile))
{
while (reader.ReadLine() != null)
{
totalLines++;
}
}
Console.WriteLine($"总行数: {totalLines}");
}
finally
{
if (File.Exists(largeFile))
{
File.Delete(largeFile);
Console.WriteLine("\n清理大文件");
}
}
}
}
3. 二进制文件操作
3.1 BinaryReader和BinaryWriter
public class BinaryFileOperations
{
public static void DemonstrateBinaryOperations()
{
Console.WriteLine("\n=== 二进制文件操作演示 ===");
Console.WriteLine("\n--- 基本二进制读写 ---");
BasicBinaryOperations();
Console.WriteLine("\n--- 复杂数据结构 ---");
ComplexDataStructures();
Console.WriteLine("\n--- 二进制文件格式 ---");
CustomBinaryFormat();
}
private static void BasicBinaryOperations()
{
string binaryFile = Path.Combine(Path.GetTempPath(), "binary_test.dat");
try
{
// 写入二进制数据
using (var fileStream = new FileStream(binaryFile, FileMode.Create))
using (var writer = new BinaryWriter(fileStream))
{
// 写入各种数据类型
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!"); // string
writer.Write(DateTime.Now.ToBinary()); // DateTime as binary
// 写入字节数组
byte[] byteArray = { 1, 2, 3, 4, 5 };
writer.Write(byteArray.Length);
writer.Write(byteArray);
Console.WriteLine("二进制数据写入完成");
}
// 读取二进制数据
using (var fileStream = new FileStream(binaryFile, FileMode.Open))
using (var reader = new BinaryReader(fileStream))
{
Console.WriteLine("\n读取二进制数据:");
bool boolValue = reader.ReadBoolean();
byte byteValue = reader.ReadByte();
short shortValue = reader.ReadInt16();
int intValue = reader.ReadInt32();
long longValue = reader.ReadInt64();
float floatValue = reader.ReadSingle();
double doubleValue = reader.ReadDouble();
char charValue = reader.ReadChar();
string stringValue = reader.ReadString();
DateTime dateTimeValue = DateTime.FromBinary(reader.ReadInt64());
Console.WriteLine($"bool: {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($"DateTime: {dateTimeValue}");
// 读取字节数组
int arrayLength = reader.ReadInt32();
byte[] readByteArray = reader.ReadBytes(arrayLength);
Console.WriteLine($"byte array: [{string.Join(", ", readByteArray)}]");
}
var fileInfo = new FileInfo(binaryFile);
Console.WriteLine($"\n二进制文件大小: {fileInfo.Length} 字节");
}
finally
{
if (File.Exists(binaryFile))
{
File.Delete(binaryFile);
}
}
}
private static void ComplexDataStructures()
{
string dataFile = Path.Combine(Path.GetTempPath(), "complex_data.dat");
// 定义复杂数据结构
var students = new List<StudentRecord>
{
new StudentRecord { Id = 1, Name = "张三", Age = 20, GPA = 3.8, Courses = new[] { "数学", "物理", "编程" } },
new StudentRecord { Id = 2, Name = "李四", Age = 21, GPA = 3.6, Courses = new[] { "化学", "生物" } },
new StudentRecord { Id = 3, Name = "王五", Age = 19, GPA = 3.9, Courses = new[] { "历史", "地理", "政治", "语文" } }
};
try
{
// 写入复杂数据结构
using (var fileStream = new FileStream(dataFile, FileMode.Create))
using (var writer = new BinaryWriter(fileStream))
{
// 写入文件头
writer.Write("STUDENT_DATA"); // 文件标识
writer.Write((byte)1); // 版本号
writer.Write(students.Count); // 记录数量
foreach (var student in students)
{
WriteStudentRecord(writer, student);
}
Console.WriteLine($"写入 {students.Count} 个学生记录");
}
// 读取复杂数据结构
using (var fileStream = new FileStream(dataFile, FileMode.Open))
using (var reader = new BinaryReader(fileStream))
{
// 读取文件头
string fileId = reader.ReadString();
byte version = reader.ReadByte();
int recordCount = reader.ReadInt32();
Console.WriteLine($"\n文件标识: {fileId}");
Console.WriteLine($"版本: {version}");
Console.WriteLine($"记录数量: {recordCount}");
Console.WriteLine("\n读取学生记录:");
for (int i = 0; i < recordCount; i++)
{
var student = ReadStudentRecord(reader);
Console.WriteLine($" {student.Id}: {student.Name}, {student.Age}岁, GPA: {student.GPA}");
Console.WriteLine($" 课程: {string.Join(", ", student.Courses)}");
}
}
}
finally
{
if (File.Exists(dataFile))
{
File.Delete(dataFile);
}
}
}
private static void WriteStudentRecord(BinaryWriter writer, StudentRecord student)
{
writer.Write(student.Id);
writer.Write(student.Name);
writer.Write(student.Age);
writer.Write(student.GPA);
// 写入课程数组
writer.Write(student.Courses.Length);
foreach (string course in student.Courses)
{
writer.Write(course);
}
}
private static StudentRecord ReadStudentRecord(BinaryReader reader)
{
var student = new StudentRecord
{
Id = reader.ReadInt32(),
Name = reader.ReadString(),
Age = reader.ReadInt32(),
GPA = reader.ReadDouble()
};
// 读取课程数组
int courseCount = reader.ReadInt32();
student.Courses = new string[courseCount];
for (int i = 0; i < courseCount; i++)
{
student.Courses[i] = reader.ReadString();
}
return student;
}
private static void CustomBinaryFormat()
{
string formatFile = Path.Combine(Path.GetTempPath(), "custom_format.dat");
try
{
// 创建自定义二进制格式
using (var fileStream = new FileStream(formatFile, FileMode.Create))
using (var writer = new BinaryWriter(fileStream))
{
// 文件头 (16字节)
writer.Write(Encoding.ASCII.GetBytes("MYFORMAT")); // 8字节标识
writer.Write((ushort)1); // 2字节主版本
writer.Write((ushort)0); // 2字节次版本
writer.Write((uint)0); // 4字节保留字段
// 数据块1: 配置信息
WriteDataBlock(writer, "CONFIG", () =>
{
writer.Write("MyApplication"); // 应用名称
writer.Write(true); // 启用调试
writer.Write(1024); // 缓冲区大小
});
// 数据块2: 用户数据
WriteDataBlock(writer, "USERS", () =>
{
var users = new[] { "admin", "user1", "user2" };
writer.Write(users.Length);
foreach (string user in users)
{
writer.Write(user);
writer.Write(DateTime.Now.ToBinary()); // 创建时间
}
});
// 数据块3: 统计信息
WriteDataBlock(writer, "STATS", () =>
{
writer.Write(12345L); // 总访问次数
writer.Write(678.9); // 平均响应时间
writer.Write((byte)95); // 成功率百分比
});
Console.WriteLine("自定义格式文件创建完成");
}
// 读取自定义格式
using (var fileStream = new FileStream(formatFile, FileMode.Open))
using (var reader = new BinaryReader(fileStream))
{
// 读取文件头
byte[] signature = reader.ReadBytes(8);
ushort majorVersion = reader.ReadUInt16();
ushort minorVersion = reader.ReadUInt16();
uint reserved = reader.ReadUInt32();
string signatureStr = Encoding.ASCII.GetString(signature);
Console.WriteLine($"\n文件签名: {signatureStr}");
Console.WriteLine($"版本: {majorVersion}.{minorVersion}");
// 读取数据块
while (fileStream.Position < fileStream.Length)
{
var (blockType, blockData) = ReadDataBlock(reader);
Console.WriteLine($"\n数据块类型: {blockType}");
Console.WriteLine($"数据块大小: {blockData.Length} 字节");
// 解析特定数据块
using (var blockStream = new MemoryStream(blockData))
using (var blockReader = new BinaryReader(blockStream))
{
ParseDataBlock(blockType, blockReader);
}
}
}
}
finally
{
if (File.Exists(formatFile))
{
File.Delete(formatFile);
}
}
}
private static void WriteDataBlock(BinaryWriter writer, string blockType, Action writeData)
{
// 写入块类型 (8字节,不足补0)
byte[] typeBytes = new byte[8];
byte[] actualBytes = Encoding.ASCII.GetBytes(blockType);
Array.Copy(actualBytes, typeBytes, Math.Min(actualBytes.Length, 8));
writer.Write(typeBytes);
// 使用内存流计算数据大小
using (var dataStream = new MemoryStream())
using (var dataWriter = new BinaryWriter(dataStream))
{
writeData();
byte[] data = dataStream.ToArray();
writer.Write((uint)data.Length); // 写入数据大小
writer.Write(data); // 写入数据
}
}
private static (string BlockType, byte[] Data) ReadDataBlock(BinaryReader reader)
{
byte[] typeBytes = reader.ReadBytes(8);
string blockType = Encoding.ASCII.GetString(typeBytes).TrimEnd('\0');
uint dataSize = reader.ReadUInt32();
byte[] data = reader.ReadBytes((int)dataSize);
return (blockType, data);
}
private static void ParseDataBlock(string blockType, BinaryReader reader)
{
switch (blockType)
{
case "CONFIG":
string appName = reader.ReadString();
bool debugEnabled = reader.ReadBoolean();
int bufferSize = reader.ReadInt32();
Console.WriteLine($" 应用名称: {appName}");
Console.WriteLine($" 调试模式: {debugEnabled}");
Console.WriteLine($" 缓冲区大小: {bufferSize}");
break;
case "USERS":
int userCount = reader.ReadInt32();
Console.WriteLine($" 用户数量: {userCount}");
for (int i = 0; i < userCount; i++)
{
string userName = reader.ReadString();
DateTime createTime = DateTime.FromBinary(reader.ReadInt64());
Console.WriteLine($" {userName} - {createTime:yyyy-MM-dd HH:mm:ss}");
}
break;
case "STATS":
long totalVisits = reader.ReadInt64();
double avgResponseTime = reader.ReadDouble();
byte successRate = reader.ReadByte();
Console.WriteLine($" 总访问次数: {totalVisits}");
Console.WriteLine($" 平均响应时间: {avgResponseTime}ms");
Console.WriteLine($" 成功率: {successRate}%");
break;
default:
Console.WriteLine($" 未知数据块类型: {blockType}");
break;
}
}
}
// 学生记录数据结构
public class StudentRecord
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public double GPA { get; set; }
public string[] Courses { get; set; }
}
4. 对象序列化
4.1 JSON序列化
using System.Text.Json;
using System.Text.Json.Serialization;
using Newtonsoft.Json;
public class JsonSerializationDemo
{
public static void DemonstrateJsonSerialization()
{
Console.WriteLine("\n=== JSON序列化演示 ===");
Console.WriteLine("\n--- System.Text.Json ---");
SystemTextJsonDemo();
Console.WriteLine("\n--- Newtonsoft.Json ---");
NewtonsoftJsonDemo();
Console.WriteLine("\n--- 复杂对象序列化 ---");
ComplexObjectSerialization();
Console.WriteLine("\n--- 自定义序列化 ---");
CustomJsonSerialization();
}
private static void SystemTextJsonDemo()
{
// 创建测试对象
var person = new Person
{
Id = 1,
Name = "张三",
Age = 30,
Email = "zhangsan@example.com",
BirthDate = new DateTime(1993, 5, 15),
IsActive = true,
Tags = new[] { "开发者", "C#", "技术" }
};
// 序列化为JSON
var options = new JsonSerializerOptions
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
string json = JsonSerializer.Serialize(person, options);
Console.WriteLine($"序列化结果:\n{json}");
// 反序列化
Person deserializedPerson = JsonSerializer.Deserialize<Person>(json, options);
Console.WriteLine($"\n反序列化结果:");
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.IsActive}");
Console.WriteLine($"标签: {string.Join(", ", deserializedPerson.Tags)}");
// 保存到文件
string jsonFile = Path.Combine(Path.GetTempPath(), "person.json");
try
{
File.WriteAllText(jsonFile, json);
Console.WriteLine($"\nJSON已保存到: {jsonFile}");
// 从文件读取
string fileJson = File.ReadAllText(jsonFile);
Person filePerson = JsonSerializer.Deserialize<Person>(fileJson, options);
Console.WriteLine($"从文件读取: {filePerson.Name}");
}
finally
{
if (File.Exists(jsonFile))
{
File.Delete(jsonFile);
}
}
}
private static void NewtonsoftJsonDemo()
{
var product = new Product
{
Id = 101,
Name = "笔记本电脑",
Price = 5999.99m,
Category = "电子产品",
InStock = true,
CreatedAt = DateTime.Now,
Specifications = new Dictionary<string, object>
{
{ "CPU", "Intel i7" },
{ "RAM", "16GB" },
{ "Storage", "512GB SSD" },
{ "Weight", 1.8 }
}
};
// Newtonsoft.Json序列化设置
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
DateFormatString = "yyyy-MM-dd HH:mm:ss",
NullValueHandling = NullValueHandling.Ignore
};
string json = JsonConvert.SerializeObject(product, settings);
Console.WriteLine($"Newtonsoft.Json序列化:\n{json}");
// 反序列化
Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json, settings);
Console.WriteLine($"\n反序列化结果:");
Console.WriteLine($"产品: {deserializedProduct.Name}");
Console.WriteLine($"价格: ¥{deserializedProduct.Price}");
Console.WriteLine($"规格:");
foreach (var spec in deserializedProduct.Specifications)
{
Console.WriteLine($" {spec.Key}: {spec.Value}");
}
}
private static void ComplexObjectSerialization()
{
// 创建复杂对象结构
var company = new Company
{
Id = 1,
Name = "科技有限公司",
Address = new Address
{
Street = "中关村大街1号",
City = "北京",
Country = "中国",
PostalCode = "100000"
},
Employees = new List<Employee>
{
new Employee
{
Id = 1,
Name = "张三",
Position = "软件工程师",
Salary = 15000,
Department = new Department { Id = 1, Name = "技术部" }
},
new Employee
{
Id = 2,
Name = "李四",
Position = "产品经理",
Salary = 18000,
Department = new Department { Id = 2, Name = "产品部" }
}
},
Founded = new DateTime(2010, 3, 15)
};
// 序列化复杂对象
var options = new JsonSerializerOptions
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
string json = JsonSerializer.Serialize(company, options);
Console.WriteLine($"复杂对象序列化:\n{json}");
// 反序列化
Company deserializedCompany = JsonSerializer.Deserialize<Company>(json, options);
Console.WriteLine($"\n反序列化验证:");
Console.WriteLine($"公司: {deserializedCompany.Name}");
Console.WriteLine($"地址: {deserializedCompany.Address.City}");
Console.WriteLine($"员工数量: {deserializedCompany.Employees.Count}");
foreach (var emp in deserializedCompany.Employees)
{
Console.WriteLine($" {emp.Name} - {emp.Position} - {emp.Department.Name}");
}
}
private static void CustomJsonSerialization()
{
var customObject = new CustomSerializationObject
{
Id = 1,
PublicData = "公开数据",
SensitiveData = "敏感数据",
CreatedAt = DateTime.Now,
Version = new Version(1, 2, 3)
};
// 使用自定义转换器
var options = new JsonSerializerOptions
{
WriteIndented = true,
Converters = { new VersionJsonConverter() }
};
string json = JsonSerializer.Serialize(customObject, options);
Console.WriteLine($"自定义序列化:\n{json}");
// 反序列化
var deserializedObject = JsonSerializer.Deserialize<CustomSerializationObject>(json, options);
Console.WriteLine($"\n反序列化结果:");
Console.WriteLine($"ID: {deserializedObject.Id}");
Console.WriteLine($"公开数据: {deserializedObject.PublicData}");
Console.WriteLine($"敏感数据: {deserializedObject.SensitiveData ?? "[已忽略]"}")
Console.WriteLine($"版本: {deserializedObject.Version}");
}
}
// 数据模型类
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 bool IsActive { get; set; }
public string[] Tags { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
public bool InStock { get; set; }
public DateTime CreatedAt { get; set; }
public Dictionary<string, object> Specifications { get; set; }
}
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public List<Employee> Employees { get; set; }
public DateTime Founded { get; set; }
}
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string PostalCode { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string Position { get; set; }
public decimal Salary { get; set; }
public Department Department { get; set; }
}
public class Department
{
public int Id { get; set; }
public string Name { get; set; }
}
public class CustomSerializationObject
{
public int Id { get; set; }
public string PublicData { get; set; }
[JsonIgnore]
public string SensitiveData { get; set; }
[JsonPropertyName("created_timestamp")]
public DateTime CreatedAt { get; set; }
public Version Version { get; set; }
}
// 自定义JSON转换器
public class VersionJsonConverter : JsonConverter<Version>
{
public override Version Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string versionString = reader.GetString();
return Version.Parse(versionString);
}
public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
4.2 XML序列化
using System.Xml;
using System.Xml.Serialization;
public class XmlSerializationDemo
{
public static void DemonstrateXmlSerialization()
{
Console.WriteLine("\n=== XML序列化演示 ===");
Console.WriteLine("\n--- 基本XML序列化 ---");
BasicXmlSerialization();
Console.WriteLine("\n--- 复杂XML序列化 ---");
ComplexXmlSerialization();
Console.WriteLine("\n--- 自定义XML序列化 ---");
CustomXmlSerialization();
}
private static void BasicXmlSerialization()
{
var book = new Book
{
Id = 1,
Title = "C#编程指南",
Author = "张三",
Price = 89.99m,
PublishDate = new DateTime(2023, 6, 15),
ISBN = "978-7-111-12345-6",
InStock = true
};
string xmlFile = Path.Combine(Path.GetTempPath(), "book.xml");
try
{
// XML序列化
var serializer = new XmlSerializer(typeof(Book));
using (var writer = new StreamWriter(xmlFile))
{
serializer.Serialize(writer, book);
}
Console.WriteLine($"XML已保存到: {xmlFile}");
// 读取并显示XML内容
string xmlContent = File.ReadAllText(xmlFile);
Console.WriteLine($"\nXML内容:\n{xmlContent}");
// XML反序列化
using (var reader = new StreamReader(xmlFile))
{
Book deserializedBook = (Book)serializer.Deserialize(reader);
Console.WriteLine($"\n反序列化结果:");
Console.WriteLine($"书名: {deserializedBook.Title}");
Console.WriteLine($"作者: {deserializedBook.Author}");
Console.WriteLine($"价格: ¥{deserializedBook.Price}");
Console.WriteLine($"出版日期: {deserializedBook.PublishDate:yyyy-MM-dd}");
Console.WriteLine($"ISBN: {deserializedBook.ISBN}");
Console.WriteLine($"库存: {deserializedBook.InStock}");
}
}
finally
{
if (File.Exists(xmlFile))
{
File.Delete(xmlFile);
}
}
}
private static void ComplexXmlSerialization()
{
var library = new Library
{
Name = "市图书馆",
Address = "文化路123号",
Books = new List<BookInfo>
{
new BookInfo
{
Id = 1,
Title = "C#高级编程",
Authors = new[] { "张三", "李四" },
Categories = new[] { "编程", "技术", "计算机" },
Details = new BookDetails
{
Pages = 500,
Language = "中文",
Publisher = "机械工业出版社"
}
},
new BookInfo
{
Id = 2,
Title = "数据结构与算法",
Authors = new[] { "王五" },
Categories = new[] { "算法", "数据结构" },
Details = new BookDetails
{
Pages = 350,
Language = "中文",
Publisher = "清华大学出版社"
}
}
}
};
string xmlFile = Path.Combine(Path.GetTempPath(), "library.xml");
try
{
// 序列化复杂对象
var serializer = new XmlSerializer(typeof(Library));
var settings = new XmlWriterSettings
{
Indent = true,
IndentChars = " ",
Encoding = Encoding.UTF8
};
using (var writer = XmlWriter.Create(xmlFile, settings))
{
serializer.Serialize(writer, library);
}
Console.WriteLine($"复杂XML已保存到: {xmlFile}");
// 显示XML内容
string xmlContent = File.ReadAllText(xmlFile, Encoding.UTF8);
Console.WriteLine($"\nXML内容:\n{xmlContent}");
// 反序列化
using (var reader = XmlReader.Create(xmlFile))
{
Library deserializedLibrary = (Library)serializer.Deserialize(reader);
Console.WriteLine($"\n反序列化结果:");
Console.WriteLine($"图书馆: {deserializedLibrary.Name}");
Console.WriteLine($"地址: {deserializedLibrary.Address}");
Console.WriteLine($"图书数量: {deserializedLibrary.Books.Count}");
foreach (var book in deserializedLibrary.Books)
{
Console.WriteLine($"\n 书名: {book.Title}");
Console.WriteLine($" 作者: {string.Join(", ", book.Authors)}");
Console.WriteLine($" 分类: {string.Join(", ", book.Categories)}");
Console.WriteLine($" 页数: {book.Details.Pages}");
Console.WriteLine($" 出版社: {book.Details.Publisher}");
}
}
}
finally
{
if (File.Exists(xmlFile))
{
File.Delete(xmlFile);
}
}
}
private static void CustomXmlSerialization()
{
var config = new ApplicationConfig
{
AppName = "MyApplication",
Version = "1.0.0",
DatabaseSettings = new DatabaseConfig
{
ConnectionString = "Server=localhost;Database=MyDB",
Timeout = 30,
EnableLogging = true
},
Features = new List<FeatureConfig>
{
new FeatureConfig { Name = "Authentication", Enabled = true, Settings = new Dictionary<string, string> { { "Provider", "OAuth" } } },
new FeatureConfig { Name = "Caching", Enabled = false, Settings = new Dictionary<string, string> { { "Type", "Redis" } } }
}
};
string xmlFile = Path.Combine(Path.GetTempPath(), "config.xml");
try
{
// 自定义XML序列化
var serializer = new XmlSerializer(typeof(ApplicationConfig));
var namespaces = new XmlSerializerNamespaces();
namespaces.Add("app", "http://mycompany.com/application");
var settings = new XmlWriterSettings
{
Indent = true,
IndentChars = " ",
Encoding = Encoding.UTF8
};
using (var writer = XmlWriter.Create(xmlFile, settings))
{
serializer.Serialize(writer, config, namespaces);
}
Console.WriteLine($"自定义XML已保存到: {xmlFile}");
// 显示XML内容
string xmlContent = File.ReadAllText(xmlFile, Encoding.UTF8);
Console.WriteLine($"\nXML内容:\n{xmlContent}");
// 反序列化
using (var reader = XmlReader.Create(xmlFile))
{
ApplicationConfig deserializedConfig = (ApplicationConfig)serializer.Deserialize(reader);
Console.WriteLine($"\n反序列化结果:");
Console.WriteLine($"应用名称: {deserializedConfig.AppName}");
Console.WriteLine($"版本: {deserializedConfig.Version}");
Console.WriteLine($"数据库连接: {deserializedConfig.DatabaseSettings.ConnectionString}");
Console.WriteLine($"功能配置:");
foreach (var feature in deserializedConfig.Features)
{
Console.WriteLine($" {feature.Name}: {(feature.Enabled ? "启用" : "禁用")}");
foreach (var setting in feature.Settings)
{
Console.WriteLine($" {setting.Key} = {setting.Value}");
}
}
}
}
finally
{
if (File.Exists(xmlFile))
{
File.Delete(xmlFile);
}
}
}
}
// XML序列化数据模型
[XmlRoot("Book")]
public class Book
{
[XmlAttribute("id")]
public int Id { get; set; }
[XmlElement("Title")]
public string Title { get; set; }
[XmlElement("Author")]
public string Author { get; set; }
[XmlElement("Price")]
public decimal Price { get; set; }
[XmlElement("PublishDate")]
public DateTime PublishDate { get; set; }
[XmlElement("ISBN")]
public string ISBN { get; set; }
[XmlElement("InStock")]
public bool InStock { get; set; }
}
[XmlRoot("Library")]
public class Library
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlElement("Address")]
public string Address { get; set; }
[XmlArray("Books")]
[XmlArrayItem("Book")]
public List<BookInfo> Books { get; set; }
}
public class BookInfo
{
[XmlAttribute("id")]
public int Id { get; set; }
[XmlElement("Title")]
public string Title { get; set; }
[XmlArray("Authors")]
[XmlArrayItem("Author")]
public string[] Authors { get; set; }
[XmlArray("Categories")]
[XmlArrayItem("Category")]
public string[] Categories { get; set; }
[XmlElement("Details")]
public BookDetails Details { get; set; }
}
public class BookDetails
{
[XmlElement("Pages")]
public int Pages { get; set; }
[XmlElement("Language")]
public string Language { get; set; }
[XmlElement("Publisher")]
public string Publisher { get; set; }
}
[XmlRoot("Configuration", Namespace = "http://mycompany.com/application")]
public class ApplicationConfig
{
[XmlAttribute("name")]
public string AppName { get; set; }
[XmlAttribute("version")]
public string Version { get; set; }
[XmlElement("Database")]
public DatabaseConfig DatabaseSettings { get; set; }
[XmlArray("Features")]
[XmlArrayItem("Feature")]
public List<FeatureConfig> Features { get; set; }
}
public class DatabaseConfig
{
[XmlElement("ConnectionString")]
public string ConnectionString { get; set; }
[XmlElement("Timeout")]
public int Timeout { get; set; }
[XmlElement("EnableLogging")]
public bool EnableLogging { get; set; }
}
public class FeatureConfig
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("enabled")]
public bool Enabled { get; set; }
[XmlIgnore]
public Dictionary<string, string> Settings { get; set; } = new Dictionary<string, string>();
[XmlArray("Settings")]
[XmlArrayItem("Setting")]
public SettingItem[] SettingsArray
{
get
{
return Settings?.Select(kvp => new SettingItem { Key = kvp.Key, Value = kvp.Value }).ToArray();
}
set
{
Settings = value?.ToDictionary(item => item.Key, item => item.Value) ?? new Dictionary<string, string>();
}
}
}
public class SettingItem
{
[XmlAttribute("key")]
public string Key { get; set; }
[XmlAttribute("value")]
public string Value { get; set; }
}
二进制序列化
1. BinaryFormatter(已过时)
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
public class LegacyData
{
public string Name { get; set; }
public int Value { get; set; }
public DateTime CreatedAt { get; set; }
}
public class LegacyBinarySerialization
{
// 注意:BinaryFormatter在.NET 5+中已被标记为过时
// 仅用于演示,实际项目中不推荐使用
public static void SerializeToFile(object obj, string filePath)
{
using var stream = new FileStream(filePath, FileMode.Create);
var formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
}
public static T DeserializeFromFile<T>(string filePath)
{
using var stream = new FileStream(filePath, FileMode.Open);
var formatter = new BinaryFormatter();
return (T)formatter.Deserialize(stream);
}
}
2. 现代二进制序列化方案
using System;
using System.IO;
using System.Text.Json;
using MessagePack;
// MessagePack序列化(推荐的二进制序列化方案)
[MessagePackObject]
public class ModernData
{
[Key(0)]
public string Name { get; set; }
[Key(1)]
public int Value { get; set; }
[Key(2)]
public DateTime CreatedAt { get; set; }
[Key(3)]
public List<string> Tags { get; set; } = new();
}
public class ModernBinarySerialization
{
// MessagePack序列化
public static byte[] SerializeMessagePack<T>(T obj)
{
return MessagePackSerializer.Serialize(obj);
}
public static T DeserializeMessagePack<T>(byte[] data)
{
return MessagePackSerializer.Deserialize<T>(data);
}
// 使用System.Text.Json的UTF8字节序列化
public static byte[] SerializeJsonUtf8<T>(T obj)
{
return JsonSerializer.SerializeToUtf8Bytes(obj);
}
public static T DeserializeJsonUtf8<T>(byte[] data)
{
return JsonSerializer.Deserialize<T>(data);
}
// 自定义二进制协议
public static byte[] SerializeCustom(ModernData data)
{
using var stream = new MemoryStream();
using var writer = new BinaryWriter(stream);
// 写入版本号
writer.Write((byte)1);
// 写入字符串
writer.Write(data.Name ?? string.Empty);
// 写入整数
writer.Write(data.Value);
// 写入日期时间
writer.Write(data.CreatedAt.ToBinary());
// 写入标签列表
writer.Write(data.Tags.Count);
foreach (var tag in data.Tags)
{
writer.Write(tag);
}
return stream.ToArray();
}
public static ModernData DeserializeCustom(byte[] data)
{
using var stream = new MemoryStream(data);
using var reader = new BinaryReader(stream);
// 读取版本号
var version = reader.ReadByte();
if (version != 1)
throw new InvalidDataException($"Unsupported version: {version}");
var result = new ModernData
{
Name = reader.ReadString(),
Value = reader.ReadInt32(),
CreatedAt = DateTime.FromBinary(reader.ReadInt64())
};
// 读取标签列表
var tagCount = reader.ReadInt32();
for (int i = 0; i < tagCount; i++)
{
result.Tags.Add(reader.ReadString());
}
return result;
}
}
高级序列化技术
1. 自定义序列化控制
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
public class AdvancedSerializationControl
{
[JsonPropertyName("full_name")]
public string Name { get; set; }
[JsonIgnore]
public string Password { get; set; }
[JsonPropertyName("birth_date")]
[JsonConverter(typeof(DateOnlyJsonConverter))]
public DateOnly BirthDate { get; set; }
[JsonPropertyName("metadata")]
[JsonConverter(typeof(DictionaryStringObjectJsonConverter))]
public Dictionary<string, object> Metadata { get; set; } = new();
// 条件序列化
public bool ShouldSerializePassword() => false;
// 序列化回调
[JsonExtensionData]
public Dictionary<string, JsonElement> ExtensionData { get; set; }
}
// 自定义日期转换器
public class DateOnlyJsonConverter : JsonConverter<DateOnly>
{
public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return DateOnly.ParseExact(reader.GetString(), "yyyy-MM-dd");
}
public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString("yyyy-MM-dd"));
}
}
// 自定义字典转换器
public class DictionaryStringObjectJsonConverter : JsonConverter<Dictionary<string, object>>
{
public override Dictionary<string, object> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var dictionary = new Dictionary<string, object>();
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
return dictionary;
if (reader.TokenType != JsonTokenType.PropertyName)
throw new JsonException();
string propertyName = reader.GetString();
reader.Read();
dictionary[propertyName] = ReadValue(ref reader);
}
throw new JsonException();
}
private object ReadValue(ref Utf8JsonReader reader)
{
return reader.TokenType switch
{
JsonTokenType.String => reader.GetString(),
JsonTokenType.Number => reader.TryGetInt32(out int intValue) ? intValue : reader.GetDouble(),
JsonTokenType.True => true,
JsonTokenType.False => false,
JsonTokenType.Null => null,
_ => throw new JsonException($"Unsupported token type: {reader.TokenType}")
};
}
public override void Write(Utf8JsonWriter writer, Dictionary<string, object> value, JsonSerializerOptions options)
{
writer.WriteStartObject();
foreach (var kvp in value)
{
writer.WritePropertyName(kvp.Key);
WriteValue(writer, kvp.Value);
}
writer.WriteEndObject();
}
private void WriteValue(Utf8JsonWriter writer, object value)
{
switch (value)
{
case null:
writer.WriteNullValue();
break;
case string s:
writer.WriteStringValue(s);
break;
case int i:
writer.WriteNumberValue(i);
break;
case double d:
writer.WriteNumberValue(d);
break;
case bool b:
writer.WriteBooleanValue(b);
break;
default:
writer.WriteStringValue(value.ToString());
break;
}
}
}
2. 流式序列化
using System;
using System.IO;
using System.Text.Json;
using System.Collections.Generic;
public class StreamingSerialization
{
// 流式写入大量数据
public static async Task WriteJsonStreamAsync<T>(IEnumerable<T> items, Stream stream)
{
using var writer = new Utf8JsonWriter(stream);
writer.WriteStartArray();
foreach (var item in items)
{
JsonSerializer.Serialize(writer, item);
await writer.FlushAsync();
}
writer.WriteEndArray();
await writer.FlushAsync();
}
// 流式读取大量数据
public static async IAsyncEnumerable<T> ReadJsonStreamAsync<T>(Stream stream)
{
using var document = await JsonDocument.ParseAsync(stream);
if (document.RootElement.ValueKind != JsonValueKind.Array)
throw new JsonException("Expected JSON array");
foreach (var element in document.RootElement.EnumerateArray())
{
yield return JsonSerializer.Deserialize<T>(element.GetRawText());
}
}
// 分块处理大文件
public static async Task ProcessLargeJsonFileAsync<T>(string filePath, Func<T, Task> processor)
{
using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
await foreach (var item in ReadJsonStreamAsync<T>(fileStream))
{
await processor(item);
}
}
}
// 使用示例
public class StreamingDemo
{
public static async Task DemoStreamingSerialization()
{
var largeDataSet = GenerateLargeDataSet(100000);
// 写入大文件
using (var fileStream = new FileStream("large_data.json", FileMode.Create))
{
await StreamingSerialization.WriteJsonStreamAsync(largeDataSet, fileStream);
}
// 流式处理大文件
await StreamingSerialization.ProcessLargeJsonFileAsync<DataItem>(
"large_data.json",
async item =>
{
// 处理每个数据项
Console.WriteLine($"Processing: {item.Id}");
await Task.Delay(1); // 模拟处理时间
});
}
private static IEnumerable<DataItem> GenerateLargeDataSet(int count)
{
for (int i = 0; i < count; i++)
{
yield return new DataItem
{
Id = i,
Name = $"Item_{i}",
Value = Random.Shared.NextDouble() * 1000,
CreatedAt = DateTime.Now.AddDays(-Random.Shared.Next(365))
};
}
}
}
public class DataItem
{
public int Id { get; set; }
public string Name { get; set; }
public double Value { get; set; }
public DateTime CreatedAt { get; set; }
}
性能优化和最佳实践
1. 序列化性能优化
using System;
using System.Buffers;
using System.IO;
using System.Text.Json;
using System.Diagnostics;
public class SerializationPerformance
{
// 使用ArrayPool减少内存分配
public static byte[] SerializeWithArrayPool<T>(T obj)
{
var bufferWriter = new ArrayBufferWriter<byte>();
using var writer = new Utf8JsonWriter(bufferWriter);
JsonSerializer.Serialize(writer, obj);
return bufferWriter.WrittenSpan.ToArray();
}
// 预编译序列化器
private static readonly JsonSerializerOptions _optimizedOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = false
};
public static string SerializeOptimized<T>(T obj)
{
return JsonSerializer.Serialize(obj, _optimizedOptions);
}
// 性能测试
public static void BenchmarkSerialization<T>(T testObject, int iterations = 10000)
{
var stopwatch = Stopwatch.StartNew();
// 测试标准序列化
stopwatch.Restart();
for (int i = 0; i < iterations; i++)
{
JsonSerializer.Serialize(testObject);
}
stopwatch.Stop();
Console.WriteLine($"Standard serialization: {stopwatch.ElapsedMilliseconds}ms");
// 测试优化序列化
stopwatch.Restart();
for (int i = 0; i < iterations; i++)
{
SerializeOptimized(testObject);
}
stopwatch.Stop();
Console.WriteLine($"Optimized serialization: {stopwatch.ElapsedMilliseconds}ms");
// 测试ArrayPool序列化
stopwatch.Restart();
for (int i = 0; i < iterations; i++)
{
SerializeWithArrayPool(testObject);
}
stopwatch.Stop();
Console.WriteLine($"ArrayPool serialization: {stopwatch.ElapsedMilliseconds}ms");
}
}
2. 文件操作最佳实践
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
public class FileOperationBestPractices
{
// 安全的文件写入(原子操作)
public static async Task SafeWriteAllTextAsync(string filePath, string content)
{
var tempPath = filePath + ".tmp";
try
{
await File.WriteAllTextAsync(tempPath, content);
// 原子性替换
if (File.Exists(filePath))
{
File.Replace(tempPath, filePath, filePath + ".bak");
}
else
{
File.Move(tempPath, filePath);
}
}
catch
{
// 清理临时文件
if (File.Exists(tempPath))
{
File.Delete(tempPath);
}
throw;
}
}
// 带重试的文件操作
public static async Task<T> RetryFileOperation<T>(Func<Task<T>> operation, int maxRetries = 3)
{
for (int i = 0; i < maxRetries; i++)
{
try
{
return await operation();
}
catch (IOException) when (i < maxRetries - 1)
{
await Task.Delay(TimeSpan.FromMilliseconds(100 * Math.Pow(2, i)));
}
}
return await operation(); // 最后一次尝试,不捕获异常
}
// 文件完整性验证
public static async Task<bool> VerifyFileIntegrityAsync(string filePath, string expectedHash)
{
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
using var sha256 = SHA256.Create();
var hash = await sha256.ComputeHashAsync(stream);
var hashString = Convert.ToHexString(hash);
return string.Equals(hashString, expectedHash, StringComparison.OrdinalIgnoreCase);
}
// 大文件分块处理
public static async Task ProcessLargeFileAsync(string filePath, Func<ReadOnlyMemory<byte>, Task> processor, int bufferSize = 8192)
{
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var buffer = new byte[bufferSize];
int bytesRead;
while ((bytesRead = await stream.ReadAsync(buffer)) > 0)
{
await processor(buffer.AsMemory(0, bytesRead));
}
}
// 并发安全的文件访问
private static readonly SemaphoreSlim _fileSemaphore = new(1, 1);
public static async Task<string> SafeReadAllTextAsync(string filePath)
{
await _fileSemaphore.WaitAsync();
try
{
return await File.ReadAllTextAsync(filePath);
}
finally
{
_fileSemaphore.Release();
}
}
}