I/O(输入/输出)操作是计算机程序中不可或缺的一部分,无论是读取文件、写入数据,还是处理网络通信,I/O都发挥着重要作用。C#作为一种现代化的编程语言,提供了丰富的I/O操作支持,包括文件I/O、流操作、网络I/O等。本文将深入探讨C#中的流与I/O,从基本概念到高级用法,全面解析I/O操作的原理和机制,并结合实际案例,帮助读者掌握I/O编程的精髓。

I/O操作的基本概念

I/O设备

I/O设备是计算机系统中用于输入和输出数据的设备,包括键盘、鼠标、显示器、打印机、磁盘驱动器、网络接口等。I/O设备通过I/O端口与计算机系统进行通信,实现数据的输入和输出。

I/O操作类型

I/O操作可以分为两种类型:同步I/O和异步I/O。

  1. 同步I/O:同步I/O操作在执行过程中会阻塞调用线程,直到I/O操作完成。这种方式简单易用,但可能导致性能问题,特别是在高并发场景下。
  2. 异步I/O:异步I/O操作在执行过程中不会阻塞调用线程,可以通过回调、事件或任务的方式在操作完成后通知调用者。这种方式可以提高系统的并发性能,但编程相对复杂。

流的基本概念

什么是流

流(Stream)是一个抽象的概念,用于表示数据的有序序列。流可以是字节流或字符流,前者用于处理二进制数据,后者用于处理文本数据。C#中的流通过System.IO.Stream类及其派生类实现。

流的分类

根据数据流动的方向,流可以分为输入流和输出流。输入流用于从数据源读取数据,输出流用于向数据目标写入数据。

流的基本操作

流的基本操作包括读取数据、写入数据、关闭流等。C#中的Stream类及其派生类提供了这些操作的基本方法。

文件I/O操作

文件流

文件流(FileStream)是用于文件读写操作的流,通过System.IO.FileStream类实现。FileStream提供了对文件进行读写操作的基础支持。

  1. using System;
  2. using System.IO;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. string filePath = "example.txt";
  8. // 写入文件
  9. using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
  10. {
  11. byte[] data = System.Text.Encoding.UTF8.GetBytes("Hello, FileStream!");
  12. fileStream.Write(data, 0, data.Length);
  13. }
  14. // 读取文件
  15. using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
  16. {
  17. byte[] data = new byte[fileStream.Length];
  18. fileStream.Read(data, 0, data.Length);
  19. string content = System.Text.Encoding.UTF8.GetString(data);
  20. Console.WriteLine(content);
  21. }
  22. }
  23. }

在这个例子中,我们使用FileStream类分别进行文件的写入和读取操作。

文件读写快捷方法

C#中的System.IO.File类提供了一些方便的方法,用于快速进行文件的读写操作。

  1. using System;
  2. using System.IO;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. string filePath = "example.txt";
  8. // 写入文件
  9. File.WriteAllText(filePath, "Hello, File!");
  10. // 读取文件
  11. string content = File.ReadAllText(filePath);
  12. Console.WriteLine(content);
  13. }
  14. }

在这个例子中,我们使用File.WriteAllTextFile.ReadAllText方法快速进行文件的写入和读取操作。

字符流操作

StreamReader和StreamWriter

StreamReaderStreamWriter是用于读取和写入字符流的类,通过System.IO.StreamReaderSystem.IO.StreamWriter类实现。

  1. using System;
  2. using System.IO;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. string filePath = "example.txt";
  8. // 写入文件
  9. using (StreamWriter writer = new StreamWriter(filePath))
  10. {
  11. writer.WriteLine("Hello, StreamWriter!");
  12. }
  13. // 读取文件
  14. using (StreamReader reader = new StreamReader(filePath))
  15. {
  16. string content = reader.ReadToEnd();
  17. Console.WriteLine(content);
  18. }
  19. }
  20. }

在这个例子中,我们使用StreamWriterStreamReader类分别进行文件的写入和读取操作。

StringReader和StringWriter

StringReaderStringWriter是用于读取和写入字符串的类,通过System.IO.StringReaderSystem.IO.StringWriter类实现。

  1. using System;
  2. using System.IO;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. string input = "Hello, StringReader!";
  8. string output;
  9. // 写入字符串
  10. using (StringWriter writer = new StringWriter())
  11. {
  12. writer.WriteLine(input);
  13. output = writer.ToString();
  14. }
  15. // 读取字符串
  16. using (StringReader reader = new StringReader(output))
  17. {
  18. string content = reader.ReadToEnd();
  19. Console.WriteLine(content);
  20. }
  21. }
  22. }

在这个例子中,我们使用StringWriterStringReader类分别进行字符串的写入和读取操作。

缓冲流操作

BufferedStream

BufferedStream是用于提高I/O操作性能的缓冲流,通过System.IO.BufferedStream类实现。缓冲流通过减少对底层设备的直接访问次数来提高性能。

  1. using System;
  2. using System.IO;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. string filePath = "example.txt";
  8. // 写入文件
  9. using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
  10. using (BufferedStream bufferedStream = new BufferedStream(fileStream))
  11. {
  12. byte[] data = System.Text.Encoding.UTF8.GetBytes("Hello, BufferedStream!");
  13. bufferedStream.Write(data, 0, data.Length);
  14. }
  15. // 读取文件
  16. using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
  17. using (BufferedStream bufferedStream = new BufferedStream(fileStream))
  18. {
  19. byte[] data = new byte[bufferedStream.Length];
  20. bufferedStream.Read(data, 0, data.Length);
  21. string content = System.Text.Encoding.UTF8.GetString(data);
  22. Console.WriteLine(content);
  23. }
  24. }
  25. }

在这个例子中,我们使用BufferedStream类分别进行文件的写入和读取操作。

内存流操作

MemoryStream

MemoryStream是用于在内存中读写数据的流,通过System.IO.MemoryStream类实现。内存流适用于需要高效处理小数据量的场景。

  1. using System;
  2. using System.IO;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. byte[] buffer;
  8. // 写入内存流
  9. using (MemoryStream memoryStream = new MemoryStream())
  10. {
  11. byte[] data = System.Text.Encoding.UTF8.GetBytes("Hello, MemoryStream!");
  12. memoryStream.Write(data, 0, data.Length);
  13. buffer = memoryStream.ToArray();
  14. }
  15. // 读取内存流
  16. using (MemoryStream memoryStream = new MemoryStream(buffer))
  17. {
  18. byte[] data = new byte[memoryStream.Length];
  19. memoryStream.Read(data, 0, data.Length);
  20. string content = System.Text.Encoding.UTF8.GetString(data);
  21. Console.WriteLine(content);
  22. }
  23. }
  24. }

在这个例子中,我们使用MemoryStream类分别进行内存数据的写入和读取操作。

压缩流操作

GZipStream和DeflateStream

GZipStreamDeflateStream是用于数据压缩和解压缩的流,通过System.IO.Compression.GZipStreamSystem.IO.Compression.DeflateStream类实现。

  1. using System;
  2. using System.IO;
  3. using System.IO.Compression;
  4. public class Program
  5. {
  6. public static void Main(string[] args)
  7. {
  8. string filePath = "example.txt";
  9. string compressedFilePath = "example.gz";
  10. // 写入文件
  11. File.WriteAllText(filePath, "Hello, GZipStream!");
  12. // 压缩文件
  13. using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
  14. using (FileStream compressedFileStream = new FileStream(compressedFilePath, FileMode.Create, FileAccess.Write))
  15. using (GZipStream gzipStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
  16. {
  17. fileStream.CopyTo(gzipStream);
  18. }
  19. // 解压文件
  20. using (FileStream compressedFileStream = new FileStream(compressedFilePath, FileMode.Open, FileAccess
  21. .Read))
  22. using (GZipStream gzipStream = new GZipStream(compressedFileStream, CompressionMode.Decompress))
  23. using (StreamReader reader = new StreamReader(gzipStream))
  24. {
  25. string content = reader.ReadToEnd();
  26. Console.WriteLine(content);
  27. }
  28. }
  29. }

在这个例子中,我们使用GZipStream类分别进行文件的压缩和解压操作。

网络I/O操作

TcpClient和TcpListener

TcpClientTcpListener是用于TCP网络通信的类,通过System.Net.Sockets.TcpClientSystem.Net.Sockets.TcpListener类实现。

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. public class Program
  7. {
  8. public static async Task Main(string[] args)
  9. {
  10. int port = 12345;
  11. Task serverTask = StartServerAsync(port);
  12. Task clientTask = StartClientAsync(port);
  13. await Task.WhenAll(serverTask, clientTask);
  14. }
  15. public static async Task StartServerAsync(int port)
  16. {
  17. TcpListener listener = new TcpListener(IPAddress.Any, port);
  18. listener.Start();
  19. Console.WriteLine("服务器已启动");
  20. while (true)
  21. {
  22. TcpClient client = await listener.AcceptTcpClientAsync();
  23. _ = HandleClientAsync(client);
  24. }
  25. }
  26. public static async Task HandleClientAsync(TcpClient client)
  27. {
  28. NetworkStream stream = client.GetStream();
  29. byte[] buffer = new byte[1024];
  30. int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
  31. string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
  32. Console.WriteLine($"收到消息:{message}");
  33. string response = "Hello from server!";
  34. byte[] responseBytes = Encoding.UTF8.GetBytes(response);
  35. await stream.WriteAsync(responseBytes, 0, responseBytes.Length);
  36. client.Close();
  37. }
  38. public static async Task StartClientAsync(int port)
  39. {
  40. await Task.Delay(1000); // 延迟以确保服务器已启动
  41. TcpClient client = new TcpClient();
  42. await client.ConnectAsync("127.0.0.1", port);
  43. NetworkStream stream = client.GetStream();
  44. string message = "Hello from client!";
  45. byte[] messageBytes = Encoding.UTF8.GetBytes(message);
  46. await stream.WriteAsync(messageBytes, 0, messageBytes.Length);
  47. byte[] buffer = new byte[1024];
  48. int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
  49. string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
  50. Console.WriteLine($"收到响应:{response}");
  51. client.Close();
  52. }
  53. }

在这个例子中,我们使用TcpClientTcpListener类实现了一个简单的TCP网络通信示例。

HttpClient

HttpClient是用于HTTP网络通信的类,通过System.Net.Http.HttpClient类实现。

  1. using System;
  2. using System.Net.Http;
  3. using System.Threading.Tasks;
  4. public class Program
  5. {
  6. public static async Task Main(string[] args)
  7. {
  8. string url = "https://api.github.com/repos/dotnet/roslyn";
  9. HttpClient client = new HttpClient();
  10. client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (compatible; AcmeInc/1.0)");
  11. HttpResponseMessage response = await client.GetAsync(url);
  12. response.EnsureSuccessStatusCode();
  13. string content = await response.Content.ReadAsStringAsync();
  14. Console.WriteLine(content);
  15. }
  16. }

在这个例子中,我们使用HttpClient类进行HTTP GET请求,并输出响应内容。

异步I/O操作

异步文件I/O

通过使用异步方法,可以提高文件I/O操作的性能。System.IO.File类提供了多种异步方法。

  1. using System;
  2. using System.IO;
  3. using System.Text;
  4. using System.Threading.Tasks;
  5. public class Program
  6. {
  7. public static async Task Main(string[] args)
  8. {
  9. string filePath = "example.txt";
  10. // 写入文件
  11. string content = "Hello, Async File I/O!";
  12. byte[] data = Encoding.UTF8.GetBytes(content);
  13. await File.WriteAllBytesAsync(filePath, data);
  14. // 读取文件
  15. byte[] readData = await File.ReadAllBytesAsync(filePath);
  16. string readContent = Encoding.UTF8.GetString(readData);
  17. Console.WriteLine(readContent);
  18. }
  19. }

在这个例子中,我们使用异步方法分别进行文件的写入和读取操作。

异步流操作

通过使用异步方法,可以提高流操作的性能。System.IO.Stream类及其派生类提供了多种异步方法。

  1. using System;
  2. using System.IO;
  3. using System.Text;
  4. using System.Threading.Tasks;
  5. public class Program
  6. {
  7. public static async Task Main(string[] args)
  8. {
  9. string filePath = "example.txt";
  10. // 写入文件
  11. using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
  12. {
  13. byte[] data = Encoding.UTF8.GetBytes("Hello, Async FileStream!");
  14. await fileStream.WriteAsync(data, 0, data.Length);
  15. }
  16. // 读取文件
  17. using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
  18. {
  19. byte[] data = new byte[fileStream.Length];
  20. await fileStream.ReadAsync(data, 0, data.Length);
  21. string content = Encoding.UTF8.GetString(data);
  22. Console.WriteLine(content);
  23. }
  24. }
  25. }

在这个例子中,我们使用异步方法分别进行文件流的写入和读取操作。

高级I/O操作

文件监视

通过System.IO.FileSystemWatcher类,可以监视文件系统的变化,如文件创建、删除、修改等。

  1. using System;
  2. using System.IO;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. string path = ".";
  8. using (FileSystemWatcher watcher = new FileSystemWatcher())
  9. {
  10. watcher.Path = path;
  11. watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Size;
  12. watcher.Filter = "*.txt";
  13. watcher.Created += OnChanged;
  14. watcher.Changed += OnChanged;
  15. watcher.Deleted += OnChanged;
  16. watcher.Renamed += OnRenamed;
  17. watcher.EnableRaisingEvents = true;
  18. Console.WriteLine($"监视文件夹:{path}");
  19. Console.WriteLine("按回车键退出...");
  20. Console.ReadLine();
  21. }
  22. }
  23. private static void OnChanged(object source, FileSystemEventArgs e)
  24. {
  25. Console.WriteLine($"文件 {e.ChangeType}: {e.FullPath}");
  26. }
  27. private static void OnRenamed(object source, RenamedEventArgs e)
  28. {
  29. Console.WriteLine($"文件重命名: {e.OldFullPath} 改为 {e.FullPath}");
  30. }
  31. }

在这个例子中,我们使用FileSystemWatcher类监视当前文件夹中的文本文件变化,并输出变化信息。

临时文件和文件夹

通过System.IO.Path类和System.IO.File类,可以创建和使用临时文件和文件夹。

  1. using System;
  2. using System.IO;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. string tempFile = Path.GetTempFileName();
  8. string tempFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
  9. // 创建临时文件
  10. File.WriteAllText(tempFile, "Hello, Temp File!");
  11. // 创建临时文件夹
  12. Directory.CreateDirectory(tempFolder);
  13. // 输出临时文件和文件夹路径
  14. Console.WriteLine($"临时文件:{tempFile}");
  15. Console.WriteLine($"临时文件夹:{tempFolder}");
  16. // 删除临时文件和文件夹
  17. File.Delete(tempFile);
  18. Directory.Delete(tempFolder);
  19. Console.WriteLine("临时文件和文件夹已删除");
  20. }
  21. }

在这个例子中,我们使用Path.GetTempFileNamePath.GetTempPath方法创建临时文件和文件夹,并在操作完成后删除它们。

文件和目录操作

通过System.IO.File类和System.IO.Directory类,可以进行文件和目录的各种操作,如复制、移动、删除等。

  1. using System;
  2. using System.IO;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. string sourceFile = "source.txt";
  8. string destFile = "dest.txt";
  9. string sourceDir = "sourceDir";
  10. string destDir = "destDir";
  11. // 创建文件和目录
  12. File.WriteAllText(sourceFile, "Hello, File!");
  13. Directory.CreateDirectory(sourceDir);
  14. // 复制文件和目录
  15. File.Copy(sourceFile, destFile, true);
  16. DirectoryCopy(sourceDir, destDir, true);
  17. // 移动文件和目录
  18. File.Move(destFile, "moved.txt");
  19. Directory.Move(destDir, "movedDir");
  20. // 删除文件和目录
  21. File.Delete("moved.txt");
  22. Directory.Delete("movedDir", true);
  23. Console.WriteLine("文件和目录操作完成");
  24. }
  25. private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
  26. {
  27. DirectoryInfo dir = new DirectoryInfo(sourceDirName);
  28. DirectoryInfo[] dirs = dir.GetDirectories();
  29. Directory.CreateDirectory(destDirName);
  30. FileInfo[] files = dir.GetFiles();
  31. foreach (FileInfo file in files)
  32. {
  33. string tempPath = Path.Combine(destDirName, file.Name);
  34. file.CopyTo(tempPath, false);
  35. }
  36. if (copySubDirs)
  37. {
  38. foreach (DirectoryInfo subdir in dirs)
  39. {
  40. string tempPath = Path.Combine(destDirName, subdir.Name);
  41. DirectoryCopy(subdir.FullName, tempPath, copySubDirs);
  42. }
  43. }
  44. }
  45. }

在这个例子中,我们使用File类和Directory类进行文件和目录的复制、移动和删除操作。

I/O性能优化

缓冲和批量操作

通过使用缓冲和批量操作,可以减少I/O操作的次数,从而提高性能。BufferedStream类和批量读取/写入方法是实现缓冲和批量操作的常用方法。

  1. using System;
  2. using System.IO;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. string filePath = "example.txt";
  8. // 批量写入文件
  9. using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
  10. using (BufferedStream bufferedStream = new BufferedStream(fileStream))
  11. {
  12. for (int i = 0; i < 10000; i++)
  13. {
  14. byte[] data = System.Text.Encoding.UTF8.GetBytes("Hello, BufferedStream!\n");
  15. bufferedStream.Write(data, 0, data.Length);
  16. }
  17. }
  18. // 批量读取文件
  19. using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
  20. using (BufferedStream bufferedStream = new BufferedStream(fileStream))
  21. using (StreamReader reader = new StreamReader(bufferedStream))
  22. {
  23. while (!reader.EndOfStream)
  24. {
  25. string line = reader.ReadLine();
  26. // 处理读取的数据
  27. }
  28. }
  29. Console.WriteLine("文件读写完成");
  30. }
  31. }

在这个例子中,我们使用BufferedStream类进行批量写入和读取操作,以提高I/O性能。

异步I/O

通过使用异步I/O操作,可以避免阻塞调用线程,从而提高系统的并发性能。System.IO.File类和System.IO.Stream类及其派生类提供了多种异步方法。

  1. using System;
  2. using System.IO;
  3. using System.Text;
  4. using System.Threading.Tasks;
  5. public class Program
  6. {
  7. public static async Task Main(string[] args)
  8. {
  9. string filePath = "example.txt";
  10. // 异步写入文件
  11. string content = "Hello, Async File I/O!";
  12. byte[] data = Encoding.UTF8.GetBytes(content);
  13. await File.WriteAllBytesAsync(filePath, data);
  14. // 异步读取文件
  15. byte[] readData = await File.ReadAllBytesAsync(filePath);
  16. string readContent = Encoding.UTF8.GetString(readData);
  17. Console.WriteLine(readContent);
  18. }
  19. }

在这个例子中,我们使用异步方法分别进行文件的写入和读取操作,以提高I/O性能。

I/O错误处理

异常处理

在进行I/O操作时,可能会遇到各种错误情况,如文件未找到、访问权限不足、磁盘空间不足等。通过异常处理,可以捕获和处理这些错误情况。

  1. using System;
  2. using System.IO;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. string filePath = "example.txt";
  8. try
  9. {
  10. // 写入文件
  11. File.WriteAllText(filePath, "Hello, File!");
  12. // 读取文件
  13. string content = File.ReadAllText(filePath);
  14. Console.WriteLine(content);
  15. }
  16. catch (FileNotFoundException ex)
  17. {
  18. Console.WriteLine($"文件未找到:{ex.Message}");
  19. }
  20. catch (UnauthorizedAccessException ex)
  21. {
  22. Console.WriteLine($"访问权限不足:{ex.Message}");
  23. }
  24. catch (IOException ex)
  25. {
  26. Console.WriteLine($"I/O错误:{ex.Message}");
  27. }
  28. catch (Exception ex)
  29. {
  30. Console.WriteLine($"其他错误:{ex.Message}");
  31. }
  32. }
  33. }

在这个例子中,我们通过异常处理捕获并处理了文件操作中的各种错误情况。

日志记录

在进行I/O操作时,通过记录日志,可以保存错误信息和操作记录,方便后续分析和排查问题。

  1. using System;
  2. using System.IO;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. string filePath = "example.txt";
  8. try
  9. {
  10. // 写入文件
  11. File.WriteAllText(filePath, "Hello, File!");
  12. // 读取文件
  13. string content = File.ReadAllText(filePath);
  14. Console.WriteLine(content);
  15. }
  16. catch (Exception ex)
  17. {
  18. LogError(ex);
  19. }
  20. }
  21. private static void LogError(Exception ex)
  22. {
  23. string logFilePath = "error.log";
  24. string logMessage = $"{DateTime.Now}: {ex.Message}{Environment.NewLine}";
  25. File.AppendAllText(logFilePath, logMessage);
  26. }
  27. }

在这个例子中,我们通过记录日志保存了文件操作中的错误信息。

I/O的安全性

文件访问权限

在进行文件操作时,需要注意文件的访问权限。通过设置文件访问权限,可以限制对文件的读写操作,确保文件的安全性。

  1. using System;
  2. using System.IO;
  3. using System.Security.AccessControl;
  4. public class Program
  5. {
  6. public static void Main(string[] args)
  7. {
  8. string filePath = "example.txt";
  9. // 创建文件并设置访问权限
  10. File.WriteAllText(filePath, "Hello, Secure File!");
  11. FileSecurity fileSecurity = new FileSecurity();
  12. fileSecurity.AddAccessRule(new FileSystemAccessRule("Everyone", FileSystemRights.Read, AccessControlType.Allow));
  13. File.SetAccessControl(filePath, fileSecurity);
  14. // 读取文件
  15. string content = File.ReadAllText(filePath);
  16. Console.WriteLine(content);
  17. }
  18. }

在这个例子中,我们通过设置文件访问权限,限制了对文件的读写操作。

文件加密

在进行文件操作时,通过文件加密,可以保护文件内容的机密性,确保文件的安全性。

  1. using System;
  2. using System.IO;
  3. using System.Security.Cryptography;
  4. using System.Text;
  5. public class Program
  6. {
  7. public static void Main(string[] args)
  8. {
  9. string filePath = "example.txt";
  10. string encryptedFilePath = "example.encrypted";
  11. string decryptedFilePath = "example.decrypted";
  12. string content = "Hello, Secure File!";
  13. string password = "password";
  14. // 加密文件
  15. EncryptFile(filePath, encryptedFilePath, password);
  16. // 解密文件
  17. DecryptFile(encryptedFilePath, decryptedFilePath, password);
  18. // 读取解密后的文件
  19. string decryptedContent = File.ReadAllText(decryptedFilePath);
  20. Console.WriteLine(decryptedContent);
  21. }
  22. private static void EncryptFile(string inputFile, string outputFile, string password)
  23. {
  24. byte[] salt = GenerateSalt();
  25. using (Aes aes = Aes.Create())
  26. {
  27. using (Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt))
  28. {
  29. aes.Key = key.GetBytes(aes.KeySize / 8);
  30. aes.IV = key.GetBytes(aes.BlockSize / 8);
  31. using (FileStream outputStream = new FileStream(outputFile, FileMode.Create))
  32. {
  33. outputStream.Write(salt, 0, salt.Length);
  34. using (CryptoStream cryptoStream = new CryptoStream(outputStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
  35. {
  36. using (FileStream inputStream = new FileStream(inputFile, FileMode.Open))
  37. {
  38. inputStream.CopyTo(cryptoStream);
  39. }
  40. }
  41. }
  42. }
  43. }
  44. }
  45. private static void DecryptFile(string inputFile, string outputFile, string password)
  46. {
  47. byte[] salt = new byte[16];
  48. using (FileStream inputStream = new FileStream(inputFile, FileMode.Open))
  49. {
  50. inputStream.Read(salt, 0, salt.Length);
  51. using (Aes aes = Aes.Create())
  52. {
  53. using (Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt))
  54. {
  55. aes.Key = key.GetBytes(aes.KeySize / 8);
  56. aes.IV = key.GetBytes(aes.BlockSize / 8);
  57. using (CryptoStream cryptoStream = new CryptoStream(inputStream, aes.CreateDecryptor(), CryptoStreamMode.Read))
  58. {
  59. using (FileStream outputStream = new FileStream(outputFile, FileMode.Create))
  60. {
  61. cryptoStream.CopyTo(outputStream);
  62. }
  63. }
  64. }
  65. }
  66. }
  67. }
  68. private static byte[] GenerateSalt()
  69. {
  70. byte[] salt = new byte[16];
  71. using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
  72. {
  73. rng.GetBytes(salt);
  74. }
  75. return salt;
  76. }
  77. }

在这个例子中,我们通过文件加密和解密方法,保护了文件内容的机密性。

小结

I/O操作是C#编程中的一个重要方面,通过文件I/O、流操作、网络I/O等功能,开发者可以高效地处理各种数据读写和通信任务。本文深入探讨了C#中的流与I/O,从基本概念到高级用法,全面解析了I/O操作的原理和机制,并结合实际案例展示了I/O操作在文件操作、字符流操作、缓冲流操作、内存流操作、压缩流操作、网络I/O操作、异步I/O操作、高级I/O操作、I/O性能优化、I/O错误处理、I/O安全性等方面的应用。

掌握I/O操作不仅能够提高代码的健壮性和性能,还能够在复杂应用程序中发挥重要作用。希望本文能帮助读者更好地理解和掌握C#中的流与I/O,在实际开发中充分利用这一强大的编程工具。通过对I/O操作的深入理解和合理应用,可以编写出更加高效、可靠和安全的程序。