FileStream读写大文件速度慢、内存效率低的优化方案咨询
FileStream截取文件块性能优化方案
现有代码问题分析
现有实现一次性申请与待截取块(270MB)等大的字节数组存储全部数据,会触发大对象堆(LOH)分配,不仅会占用大量内存,大对象的回收还容易引发GC卡顿,额外增加耗时。
核心优化思路
不需要一次性加载全量数据,仅使用KB级的小缓冲即可在两个文件流之间循环搬运数据,内存占用稳定在KB级,IO效率也更高。
关于你问的「是否可以不使用字节数组直接通过文件流完成读写操作」:底层磁盘IO操作必须依赖字节数组作为缓冲,但你无需申请和待截取块大小一致的大数组,仅需要KB级的小缓冲即可,对上层业务逻辑来说相当于直接在两个流之间搬运数据,不会有大内存开销。
方案1:手动控制分块读写(兼容性最好,支持所有.NET版本)
你可以自定义缓冲大小(推荐32KB~128KB,性能最优),控制总读取字节数等于你要截取的块长度,代码示例如下:
' 缓冲大小设置为80KB,可根据实际场景调整 Const bufferSize As Integer = 81920 Dim remainingBytes As Integer = endOFfile ' 待读取的总字节数 Dim buffer(bufferSize - 1) As Byte Using sourceFs As New FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None, bufferSize) sourceFs.Seek(startOFfile, SeekOrigin.Begin) Using destFs As New FileStream(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.bin"), FileMode.Create, FileAccess.Write, FileShare.None, bufferSize) While remainingBytes > 0 ' 每次读取的字节数不能超过剩余待读取量和缓冲大小的最小值 Dim bytesToRead As Integer = Math.Min(bufferSize, remainingBytes) Dim bytesRead As Integer = sourceFs.Read(buffer, 0, bytesToRead) ' 读取到0字节说明已经到文件末尾,终止循环 If bytesRead = 0 Then Exit While destFs.Write(buffer, 0, bytesRead) remainingBytes -= bytesRead End While End Using End Using
方案2:使用.NET内置Stream.CopyTo方法(.NET Framework 4.0+ 支持)
如果不需要精细控制读写过程,直接用框架自带的CopyTo方法即可,内部已经做了分块优化,代码更简洁:
Const bufferSize As Integer = 81920 Using sourceFs As New FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None, bufferSize) sourceFs.Seek(startOFfile, SeekOrigin.Begin) ' 包装源流为限制长度的流,只复制指定长度的字节 Using limitedStream As New LimitedStream(sourceFs, endOFfile) Using destFs As New FileStream(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.bin"), FileMode.Create, FileAccess.Write, FileShare.None, bufferSize) limitedStream.CopyTo(destFs, bufferSize) End Using End Using End Using
注:上述代码中的LimitedStream是自定义的只允许读取固定长度的流包装类,如果不想自己实现,直接用方案1的手动循环即可,性能没有差异。
额外优化建议
- 构造FileStream时显式指定缓冲区大小,可以减少底层IO次数,提升读写速度
- 文件路径拼接推荐用
Path.Combine方法,避免手动拼接字符串出现的分隔符错误 - 如果是带UI的桌面应用,可以替换为
ReadAsync/WriteAsync或CopyToAsync异步方法,避免阻塞UI线程
内容的提问来源于stack exchange,提问作者SoftWick
相关产品推荐
相关产品推荐

