Skip to content

C# 文件 I/O

概述

文件 I/O 操作允许您读取和写入文件系统中的文件。C# 在 System.IO 命名空间中提供了全面的文件操作类。

基本文件操作

读取文件

csharp
using System.IO;

public class FileReader
{
    // 一次性读取所有文本
    public string ReadAllText(string filePath)
    {
        try
        {
            return File.ReadAllText(filePath);
        }
        catch (FileNotFoundException)
        {
            Console.WriteLine($"File not found: {filePath}");
            return string.Empty;
        }
        catch (IOException ex)
        {
            Console.WriteLine($"IO error: {ex.Message}");
            return string.Empty;
        }
    }

    // 读取所有行
    public string[] ReadAllLines(string filePath)
    {
        try
        {
            return File.ReadAllLines(filePath);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error reading file: {ex.Message}");
            return new string[0];
        }
    }

    // 使用 StreamReader 读取
    public async Task<string> ReadFileAsync(string filePath)
    {
        try
        {
            using StreamReader reader = new StreamReader(filePath);
            return await reader.ReadToEndAsync();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error reading file: {ex.Message}");
            return string.Empty;
        }
    }

    // 逐行读取
    public async Task<List<string>> ReadLinesAsync(string filePath)
    {
        var lines = new List<string>();

        try
        {
            using StreamReader reader = new StreamReader(filePath)
            {
                string line;
                while ((line = await reader.ReadLineAsync()) != null)
                {
                    lines.Add(line);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error reading file: {ex.Message}");
        }

        return lines;
    }
}

写入文件

csharp
public class FileWriter
{
    // 一次性写入所有文本
    public bool WriteAllText(string filePath, string content)
    {
        try
        {
            File.WriteAllText(filePath, content);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error writing file: {ex.Message}");
            return false;
        }
    }

    // 写入所有行
    public bool WriteAllLines(string filePath, string[] lines)
    {
        try
        {
            File.WriteAllLines(filePath, lines);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error writing file: {ex.Message}");
            return false;
        }
    }

    // 追加到文件
    public bool AppendToFile(string filePath, string content)
    {
        try
        {
            File.AppendAllText(filePath, content);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error appending to file: {ex.Message}");
            return false;
        }
    }

    // 使用 StreamWriter 写入
    public async Task<bool> WriteFileAsync(string filePath, string content)
    {
        try
        {
            using StreamWriter writer = new StreamWriter(filePath);
            await writer.WriteAsync(content);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error writing file: {ex.Message}");
            return false;
        }
    }

    // 逐行写入
    public async Task<bool> WriteLinesAsync(string filePath, List<string> lines)
    {
        try
        {
            using StreamWriter writer = new StreamWriter(filePath)
            {
                foreach (string line in lines)
                {
                    await writer.WriteLineAsync(line);
                }
            }
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error writing file: {ex.Message}");
            return false;
        }
    }
}

文件和目录操作

文件操作

csharp
public class FileOperations
{
    // 检查文件是否存在
    public bool FileExists(string filePath)
    {
        return File.Exists(filePath);
    }

    // 复制文件
    public bool CopyFile(string sourcePath, string destinationPath)
    {
        try
        {
            File.Copy(sourcePath, destinationPath, true); // 如果存在则覆盖
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error copying file: {ex.Message}");
            return false;
        }
    }

    // 移动文件
    public bool MoveFile(string sourcePath, string destinationPath)
    {
        try
        {
            File.Move(sourcePath, destinationPath);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error moving file: {ex.Message}");
            return false;
        }
    }

    // 删除文件
    public bool DeleteFile(string filePath)
    {
        try
        {
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
                return true;
            }
            return false;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error deleting file: {ex.Message}");
            return false;
        }
    }

    // 获取文件信息
    public FileInfo GetFileInfo(string filePath)
    {
        try
        {
            return new FileInfo(filePath);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error getting file info: {ex.Message}");
            return null;
        }
    }
}

目录操作

csharp
public class DirectoryOperations
{
    // 检查目录是否存在
    public bool DirectoryExists(string directoryPath)
    {
        return Directory.Exists(directoryPath);
    }

    // 创建目录
    public bool CreateDirectory(string directoryPath)
    {
        try
        {
            Directory.CreateDirectory(directoryPath);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error creating directory: {ex.Message}");
            return false;
        }
    }

    // 删除目录
    public bool DeleteDirectory(string directoryPath, bool recursive = false)
    {
        try
        {
            if (Directory.Exists(directoryPath))
            {
                Directory.Delete(directoryPath, recursive);
                return true;
            }
            return false;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error deleting directory: {ex.Message}");
            return false;
        }
    }

    // 获取目录中的文件
    public string[] GetFiles(string directoryPath, string searchPattern = "*")
    {
        try
        {
            return Directory.GetFiles(directoryPath, searchPattern);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error getting files: {ex.Message}");
            return new string[0];
        }
    }

    // 获取子目录
    public string[] GetDirectories(string directoryPath)
    {
        try
        {
            return Directory.GetDirectories(directoryPath);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error getting directories: {ex.Message}");
            return new string[0];
        }
    }

    // 移动目录
    public bool MoveDirectory(string sourcePath, string destinationPath)
    {
        try
        {
            Directory.Move(sourcePath, destinationPath);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error moving directory: {ex.Message}");
            return false;
        }
    }
}

路径操作

路径操作

csharp
public class PathOperations
{
    // 组合路径
    public string CombinePaths(params string[] paths)
    {
        return Path.Combine(paths);
    }

    // 获取目录名
    public string GetDirectoryName(string filePath)
    {
        return Path.GetDirectoryName(filePath);
    }

    // 获取文件名
    public string GetFileName(string filePath)
    {
        return Path.GetFileName(filePath);
    }

    // 获取不带扩展名的文件名
    public string GetFileNameWithoutExtension(string filePath)
    {
        return Path.GetFileNameWithoutExtension(filePath);
    }

    // 获取扩展名
    public string GetExtension(string filePath)
    {
        return Path.GetExtension(filePath);
    }

    // 更改扩展名
    public string ChangeExtension(string filePath, string newExtension)
    {
        return Path.ChangeExtension(filePath, newExtension);
    }

    // 获取绝对路径
    public string GetAbsolutePath(string relativePath)
    {
        return Path.GetFullPath(relativePath);
    }

    // 获取临时文件路径
    public string GetTempFilePath()
    {
        return Path.GetTempFileName();
    }

    // 获取随机文件名
    public string GetRandomFileName()
    {
        return Path.GetRandomFileName();
    }
}

高级文件操作

文件监控

csharp
using System.IO;

public class FileMonitor
{
    private FileSystemWatcher _watcher;

    public event EventHandler<FileEventArgs> FileCreated;
    public event EventHandler<FileEventArgs> FileDeleted;
    public event EventHandler<FileEventArgs> FileChanged;

    public void StartMonitoring(string directoryPath, string filter = "*.*")
    {
        _watcher = new FileSystemWatcher(directoryPath, filter)
        {
            NotifyFilter = NotifyFilters.FileName |
                         NotifyFilters.LastWrite |
                         NotifyFilters.Size
        };

        _watcher.Created += OnFileCreated;
        _watcher.Deleted += OnFileDeleted;
        _watcher.Changed += OnFileChanged;

        _watcher.EnableRaisingEvents = true;
        Console.WriteLine($"Started monitoring: {directoryPath}");
    }

    public void StopMonitoring()
    {
        if (_watcher != null)
        {
            _watcher.EnableRaisingEvents = false;
            _watcher.Dispose();
            Console.WriteLine("Stopped monitoring");
        }
    }

    private void OnFileCreated(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine($"File created: {e.FullPath}");
        FileCreated?.Invoke(this, new FileEventArgs(e.FullPath, "Created"));
    }

    private void OnFileDeleted(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine($"File deleted: {e.FullPath}");
        FileDeleted?.Invoke(this, new FileEventArgs(e.FullPath, "Deleted"));
    }

    private void OnFileChanged(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine($"File changed: {e.FullPath}");
        FileChanged?.Invoke(this, new FileEventArgs(e.FullPath, "Changed"));
    }
}

public class FileEventArgs : EventArgs
{
    public string FilePath { get; }
    public string Action { get; }

    public FileEventArgs(string filePath, string action)
    {
        FilePath = filePath;
        Action = action;
    }
}

文件压缩

csharp
using System.IO.Compression;

public class FileCompression
{
    // 压缩文件
    public async Task<bool> CompressFileAsync(string sourcePath, string destinationPath)
    {
        try
        {
            using FileStream sourceStream = new FileStream(sourcePath, FileMode.Open);
            using FileStream destinationStream = new FileStream(destinationPath, FileMode.Create);
            using GZipStream compressionStream = new GZipStream(destinationStream, CompressionMode.Compress)
            {
                await sourceStream.CopyToAsync(compressionStream);
            }
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error compressing file: {ex.Message}");
            return false;
        }
    }

    // 解压缩文件
    public async Task<bool> DecompressFileAsync(string sourcePath, string destinationPath)
    {
        try
        {
            using FileStream sourceStream = new FileStream(sourcePath, FileMode.Open);
            using FileStream destinationStream = new FileStream(destinationPath, FileMode.Create);
            using GZipStream decompressionStream = new GZipStream(sourceStream, CompressionMode.Decompress)
            {
                await decompressionStream.CopyToAsync(destinationStream);
            }
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error decompressing file: {ex.Message}");
            return false;
        }
    }

    // 压缩目录
    public async Task<bool> CompressDirectoryAsync(string sourceDirectory, string destinationZip)
    {
        try
        {
            await Task.Run(() => ZipFile.CreateFromDirectory(sourceDirectory, destinationZip));
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error compressing directory: {ex.Message}");
            return false;
        }
    }

    // 提取目录
    public async Task<bool> ExtractDirectoryAsync(string sourceZip, string destinationDirectory)
    {
        try
        {
            await Task.Run(() => ZipFile.ExtractToDirectory(sourceZip, destinationDirectory));
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error extracting directory: {ex.Message}");
            return false;
        }
    }
}

二进制文件操作

读写二进制文件

csharp
public class BinaryFileOperations
{
    // 写入二进制数据
    public bool WriteBinaryFile(string filePath, byte[] data)
    {
        try
        {
            File.WriteAllBytes(filePath, data);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error writing binary file: {ex.Message}");
            return false;
        }
    }

    // 读取二进制数据
    public byte[] ReadBinaryFile(string filePath)
    {
        try
        {
            return File.ReadAllBytes(filePath);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error reading binary file: {ex.Message}");
            return new byte[0];
        }
    }

    // 将对象写入二进制文件
    public bool WriteObjectToFile<T>(string filePath, T obj)
    {
        try
        {
            using FileStream stream = new FileStream(filePath, FileMode.Create);
            using BinaryWriter writer = new BinaryWriter(stream)
            {
                // 简单序列化(对于复杂对象,使用 JsonSerializer 或 BinaryFormatter)
                string json = System.Text.Json.JsonSerializer.Serialize(obj);
                writer.Write(json);
            }
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error writing object to file: {ex.Message}");
            return false;
        }
    }

    // 从二进制文件读取对象
    public T ReadObjectFromFile<T>(string filePath)
    {
        try
        {
            using FileStream stream = new FileStream(filePath, FileMode.Open);
            using BinaryReader reader = new BinaryReader(stream)
            {
                string json = reader.ReadString();
                return System.Text.Json.JsonSerializer.Deserialize<T>(json);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error reading object from file: {ex.Message}");
            return default(T);
        }
    }
}

实际示例

日志文件管理器

csharp
public class LogManager
{
    private readonly string _logDirectory;
    private readonly string _logFilePath;
    private readonly object _lockObject = new object();

    public LogManager(string logDirectory = "logs")
    {
        _logDirectory = logDirectory;

        if (!Directory.Exists(_logDirectory))
        {
            Directory.CreateDirectory(_logDirectory);
        }

        _logFilePath = Path.Combine(_logDirectory, $"app_{DateTime.Now:yyyyMMdd}.log");
    }

    public void LogInfo(string message)
    {
        Log("INFO", message);
    }

    public void LogWarning(string message)
    {
        Log("WARNING", message);
    }

    public void LogError(string message, Exception exception = null)
    {
        string fullMessage = exception != null
            ? $"{message}\nException: {exception.Message}\nStack Trace: {exception.StackTrace}"
            : message;
        Log("ERROR", fullMessage);
    }

    private void Log(string level, string message)
    {
        lock (_lockObject)
        {
            string logEntry = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [{level}] {message}";

            try
            {
                File.AppendAllText(_logFilePath, logEntry + Environment.NewLine);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Failed to write to log file: {ex.Message}");
            }
        }
    }

    public List<string> GetRecentLogs(int lines = 100)
    {
        try
        {
            if (!File.Exists(_logFilePath))
                return new List<string>();

            var allLines = File.ReadAllLines(_logFilePath);
            return allLines.TakeLast(lines).ToList();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error reading log file: {ex.Message}");
            return new List<string>();
        }
    }
}

配置管理器

csharp
public class ConfigurationManager
{
    private readonly string _configFilePath;
    private Dictionary<string, string> _settings;
    private readonly object _lockObject = new object();

    public ConfigurationManager(string configFilePath = "appsettings.json")
    {
        _configFilePath = configFilePath;
        _settings = new Dictionary<string, string>();
        LoadSettings();
    }

    public string GetSetting(string key, string defaultValue = "")
    {
        lock (_lockObject)
        {
            return _settings.TryGetValue(key, out string value) ? value : defaultValue;
        }
    }

    public void SetSetting(string key, string value)
    {
        lock (_lockObject)
        {
            _settings[key] = value;
            SaveSettings();
        }
    }

    public T GetSetting<T>(string key, T defaultValue = default(T))
    {
        string value = GetSetting(key);

        if (string.IsNullOrEmpty(value))
            return defaultValue;

        try
        {
            return (T)Convert.ChangeType(value, typeof(T));
        }
        catch
        {
            return defaultValue;
        }
    }

    private void LoadSettings()
    {
        try
        {
            if (File.Exists(_configFilePath))
            {
                string json = File.ReadAllText(_configFilePath);
                _settings = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(json)
                          ?? new Dictionary<string, string>();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error loading settings: {ex.Message}");
        }
    }

    private void SaveSettings()
    {
        try
        {
            string json = System.Text.Json.JsonSerializer.Serialize(_settings, new System.Text.Json.JsonSerializerOptions
            {
                WriteIndented = true
            });
            File.WriteAllText(_configFilePath, json);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error saving settings: {ex.Message}");
        }
    }
}

文件备份实用程序

csharp
public class FileBackupUtility
{
    public async Task<bool> BackupFilesAsync(string sourceDirectory, string backupDirectory, string[] fileExtensions = null)
    {
        try
        {
            if (!Directory.Exists(sourceDirectory))
            {
                Console.WriteLine($"Source directory does not exist: {sourceDirectory}");
                return false;
            }

            if (!Directory.Exists(backupDirectory))
            {
                Directory.CreateDirectory(backupDirectory);
            }

            string searchPattern = fileExtensions != null && fileExtensions.Length > 0
                ? "*.*"
                : "*.*";

            var files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);

            foreach (string sourceFile in files)
            {
                if (fileExtensions != null && fileExtensions.Length > 0)
                {
                    string extension = Path.GetExtension(sourceFile);
                    if (!fileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
                        continue;
                }

                string relativePath = Path.GetRelativePath(sourceDirectory, sourceFile);
                string backupFile = Path.Combine(backupDirectory, relativePath);

                string backupDir = Path.GetDirectoryName(backupFile);
                if (!Directory.Exists(backupDir))
                {
                    Directory.CreateDirectory(backupDir);
                }

                await CopyFileWithProgressAsync(sourceFile, backupFile);
            }

            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error during backup: {ex.Message}");
            return false;
        }
    }

    private async Task CopyFileWithProgressAsync(string sourceFile, string destinationFile)
    {
        using FileStream sourceStream = new FileStream(sourceFile, FileMode.Open);
        using FileStream destinationStream = new FileStream(destinationFile, FileMode.Create);
        {
            byte[] buffer = new byte[8192];
            int bytesRead;

            while ((bytesRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
            {
                await destinationStream.WriteAsync(buffer, 0, bytesRead);
            }
        }

        Console.WriteLine($"Backed up: {Path.GetFileName(sourceFile)}");
    }
}

最佳实践

文件 I/O 指南

csharp
// 好:使用 using 语句进行正确的处置
public void GoodFileHandling()
{
    using StreamReader reader = new StreamReader("file.txt")
    {
        string content = reader.ReadToEnd();
        // reader 会自动释放
    }
}

// 不好:忘记释放
public void BadFileHandling()
{
    StreamReader reader = new StreamReader("file.txt");
    string content = reader.ReadToEnd();
    // reader 未释放 - 资源泄漏
}

// 好:对 I/O 操作使用异步方法
public async Task<string> GoodAsyncFileRead()
{
    using StreamReader reader = new StreamReader("file.txt")
    {
        return await reader.ReadToEndAsync();
    }
}

// 好:正确处理异常
public bool SafeFileOperation()
{
    try
    {
        File.WriteAllText("output.txt", "content");
        return true;
    }
    catch (UnauthorizedAccessException)
    {
        Console.WriteLine("Access denied");
        return false;
    }
    catch (IOException ex)
    {
        Console.WriteLine($"IO error: {ex.Message}");
        return false;
    }
}

性能考虑

csharp
// 好:使用适当的缓冲区大小
public async Task EfficientFileCopy(string source, string destination)
{
    const int bufferSize = 8192; // 8KB 缓冲区

    using FileStream sourceStream = new FileStream(source, FileMode.Open);
    using FileStream destinationStream = new FileStream(destination, FileMode.Create);
    {
        byte[] buffer = new byte[bufferSize];
        int bytesRead;

        while ((bytesRead = await sourceStream.ReadAsync(buffer, 0, bufferSize)) > 0)
        {
            await destinationStream.WriteAsync(buffer, 0, bytesRead);
        }
    }
}

// 好:使用 FileOptions 以获得更好的性能
public async Task OptimizedFileWrite(string filePath, string content)
{
    byte[] bytes = Encoding.UTF8.GetBytes(content);

    using FileStream stream = new FileStream(
        filePath,
        FileMode.Create,
        FileAccess.Write,
        FileShare.None,
        bufferSize: 4096,
        FileOptions.Asynchronous)
    {
        await stream.WriteAsync(bytes, 0, bytes.Length);
    }
}

总结

在本章中,您学习了:

  • 基本的文件读写操作
  • 目录操作和路径处理
  • 高级文件操作,如监控和压缩
  • 二进制文件操作
  • 日志记录和配置管理等实际示例
  • 文件 I/O 操作的最佳实践
  • 性能考虑和优化技术

文件 I/O 对于许多需要持久化数据或与文件系统交互的应用程序来说是基础性的。掌握这些操作将帮助您构建健壮的数据管理解决方案。