filestream是c#中用于直接操作文件字节流的类,适用于处理二进制文件、需要精确控制文件指针或性能敏感的大文件场景;2. 使用时必须通过using语句确保资源释放,并捕获ioexception、unauthorizedaccessexception等异常以增强健壮性;3. 优化大文件处理时可设置缓冲区大小、使用readasync/writeasync异步方法、分块读写,或考虑memorymappedfile提升性能。
C#里的
FileStream
FileStream
要用
FileStream
写入文件:
想象你要把一些文字写进文件,但
FileStream
using System; using System.IO; using System.Text; // 引入这个命名空间来处理编码 public class FileWriteExample { public static void WriteToFile() { string filePath = "my_log.bin"; // 故意用.bin,表示可能不是纯文本 string content = "这是一段要写入文件的内容,可能会包含中文。"; // 将字符串内容编码成字节数组 // UTF-8 是个不错的选择,因为它兼容性好,尤其处理中文 byte[] data = Encoding.UTF8.GetBytes(content); // 使用 using 语句,确保 FileStream 在使用完毕后被正确关闭和释放 // FileMode.Create: 如果文件不存在就创建,如果存在就覆盖 // FileAccess.Write: 允许写入 try { using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { // 将字节数组写入文件 fs.Write(data, 0, data.Length); Console.WriteLine($"内容已成功写入到 {filePath}"); } } catch (IOException ex) { Console.WriteLine($"写入文件时发生IO错误:{ex.Message}"); // 真实场景中,你可能需要更详细的日志记录 } catch (UnauthorizedAccessException ex) { Console.WriteLine($"没有权限写入文件:{ex.Message}"); } catch (Exception ex) { Console.WriteLine($"发生未知错误:{ex.Message}"); } } }
读取文件:
读取文件则是一个逆向过程:从文件里读出字节,再把这些字节转换回你想要的数据类型。
using System; using System.IO; using System.Text; public class FileReadExample { public static void ReadFromFile() { string filePath = "my_log.bin"; // 在读取前,最好先检查文件是否存在 if (!File.Exists(filePath)) { Console.WriteLine($"文件 {filePath} 不存在,无法读取。"); return; } try { // FileMode.Open: 打开一个已存在的文件 // FileAccess.Read: 允许读取 using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { // 创建一个与文件大小相同的字节数组,或者一个合适的缓冲区大小 // 对于非常大的文件,不建议一次性读入所有内容,应该分块读取 byte[] buffer = new byte[fs.Length]; // 假设文件不大,一次性读完 int bytesRead = fs.Read(buffer, 0, buffer.Length); Console.WriteLine($"从文件中读取了 {bytesRead} 字节。"); // 将字节数组解码回字符串 string content = Encoding.UTF8.GetString(buffer, 0, bytesRead); Console.WriteLine("文件内容:"); Console.WriteLine(content); } } catch (IOException ex) { Console.WriteLine($"读取文件时发生IO错误:{ex.Message}"); } catch (UnauthorizedAccessException ex) { Console.WriteLine($"没有权限读取文件:{ex.Message}"); } catch (Exception ex) { Console.WriteLine($"发生未知错误:{ex.Message}"); } } }
这里只是最基础的读写。
FileStream
Seek
这俩兄弟,
FileStream
StreamReader
StreamWriter
FileStream
而
StreamReader
StreamWriter
FileStream
StreamReader
StreamWriter
\r\n
那么,什么时候该用FileStream
我的经验是,当你处理以下场景时,
FileStream
StreamReader
StreamWriter
FileStream
Seek()
StreamReader
StreamWriter
FileStream
FileStream
FileStream
什么时候用StreamReader
StreamWriter
几乎所有处理文本文件的场景。如果你只是想读写一个
.txt
.csv
.json
.xml
StreamReader
StreamWriter
所以,选择哪个,取决于你面对的是“砖头”(字节)还是“文字”(字符)。
处理大型文件,尤其是GB级别甚至TB级别的文件,直接操作很容易遇到性能瓶颈,甚至内存溢出。
FileStream
合理设置缓冲区大小:
FileStream
bufferSize
Write()
Read()
Flush()
// 创建一个带有64KB缓冲区的FileStream using (FileStream fs = new FileStream("large_file.dat", FileMode.Create, FileAccess.Write, FileShare.None, 65536)) { // ... 写入数据 }
使用异步I/O (Asynchronous I/O): 这是处理大文件时非常重要的一个优化点,尤其是在GUI应用或服务器端应用中。传统的
Read()
Write()
FileStream
ReadAsync()
WriteAsync()
await
using System.Threading.Tasks; // 引入异步相关命名空间 public static async Task WriteLargeFileAsync(string filePath, int sizeInMB) { byte[] data = new byte[1024 * 1024]; // 1MB 缓冲区 new Random().NextBytes(data); // 填充一些随机数据 try { using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, 4096, useAsync: true)) { Console.WriteLine("开始异步写入大文件..."); for (int i = 0; i < sizeInMB; i++) { await fs.WriteAsync(data, 0, data.Length); // 可以在这里报告进度,或者做其他不依赖于文件写入完成的操作 } Console.WriteLine($"异步写入 {sizeInMB}MB 完成。"); } } catch (Exception ex) { Console.WriteLine($"异步写入文件时发生错误: {ex.Message}"); } }
记住,
useAsync: true
FileStream
分块读取/写入: 对于超大文件,你不可能一次性把所有内容都加载到内存中。你需要分块(chunk)处理。比如,每次读取固定大小的块(例如4MB),处理完后再读取下一块。写入也是同理。这避免了内存溢出,并且可以让你在处理数据时保持较低的内存占用。
public static void ReadLargeFileInChunks(string filePath, int chunkSize = 4096) // 默认4KB { if (!File.Exists(filePath)) return; byte[] buffer = new byte[chunkSize]; try { using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { int bytesRead; while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0) { // 在这里处理每一块数据 // 例如:处理 buffer 中从 0 到 bytesRead-1 的数据 // Console.WriteLine($"读取了 {bytesRead} 字节..."); // 实际应用中,这里会是你的业务逻辑,比如解析、转换、写入到另一个文件等 } } } catch (Exception ex) { Console.WriteLine($"分块读取文件时发生错误: {ex.Message}"); } }
考虑MemoryMappedFile
FileStream
MemoryMappedFile
这些优化技巧,结合起来使用,能够让你在C#中更高效、更稳定地处理大型文件。
文件操作天生就是个“危险活”,磁盘可能满、文件可能被占用、路径可能不存在、权限可能不够……各种幺蛾子都可能发生。所以,在
FileStream
资源管理:IDisposable
using
FileStream
FileStream
IDisposable
Dispose()
黄金法则:永远使用using
using
IDisposable
Dispose()
// 错误示范:没有使用 using,如果在 fs.Write() 之前发生异常,文件句柄可能不会被释放 // FileStream fs = new FileStream(filePath, FileMode.Create); // fs.Write(data, 0, data.Length); // fs.Close(); // 如果写到这行前就抛异常,fs.Close() 就不会执行 // 正确且推荐的做法 try { using (FileStream fs = new FileStream("test.txt", FileMode.Create)) { // 在这里进行文件操作 // 即使这里抛出异常,fs.Dispose() 也会被调用 } // 离开 using 块时,fs.Dispose() 会自动调用 } catch (Exception ex) { Console.WriteLine($"文件操作失败:{ex.Message}"); }
如果你因为某些非常特殊的原因(比如需要在多个方法间传递一个未关闭的流,这通常是个坏设计)不能使用
using
finally
Dispose()
Close()
FileStream fs = null; try { fs = new FileStream("test.txt", FileMode.Create); // 文件操作 } catch (Exception ex) { Console.WriteLine($"文件操作失败:{ex.Message}"); } finally { // 确保 fs 不为 null 且可释放 fs?.Dispose(); // C# 6.0 及以上版本可以使用 ?. 安全调用 }
但说实话,除了极少数特殊情况,
using
异常处理:try-catch
常见的FileStream
IOException
IOException
FileNotFoundException
FileMode
Open
Append
DirectoryNotFoundException
PathTooLongException
UnauthorizedAccessException
EndOfStreamException
FileLoadException
ArgumentException
ArgumentNullException
FileStream
NotSupportedException
Write()
ObjectDisposedException
处理策略:
UnauthorizedAccessException
FileNotFoundException
一个健壮的
FileStream
try-catch-using
public static void RobustFileOperation(string filePath, string dataToWrite) { try { // 尝试写入 byte[] bytes = Encoding.UTF8.GetBytes(dataToWrite); using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { fs.Write(bytes, 0, bytes.Length); Console.WriteLine($"数据已成功写入到 {filePath}"); } // 尝试读取 using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { byte[] buffer = new byte[fs.Length]; int bytesRead = fs.Read(buffer, 0, buffer.Length); string readContent = Encoding.UTF8.GetString(buffer, 0, bytesRead); Console.WriteLine($"从 {filePath} 读取到:{readContent}"); } } catch (FileNotFoundException) { Console.WriteLine($"错误:文件 '{filePath}' 不存在。"); // 记录日志:Logger.LogError($"FileNotFound: {filePath}", ex); } catch (UnauthorizedAccessException) { Console.WriteLine($"错误:没有权限访问文件 '{filePath}',请检查文件权限。"); // 记录日志:Logger.LogError($"UnauthorizedAccess: {filePath}", ex); } catch (IOException ex) when ((ex.HResult & 0xFFFF) == 32) // 32 是文件被占用的错误码 { Console.WriteLine($"错误:文件 '{filePath}' 正在被其他程序占用,请稍后再试。"); // 记录日志:Logger.LogError($"FileInUse: {filePath}", ex); } catch (IOException ex) { Console.WriteLine($"发生
以上就是C#的FileStream类如何读写文件?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 //m.sbmmt.com/ All Rights Reserved | php.cn | 湘ICP备2023035733号