You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 19:24:04