C#分割文件方法 C#如何将大文件切割成小块

来源:这里教程网 时间:2026-02-21 17:41:41 作者:

FileStream
分块读写是最稳妥的方案

大文件不能一次性加载进内存,否则会触发

OutOfMemoryException
。必须用流式处理,逐段读取、逐段写入。核心是控制缓冲区大小(如 8192 字节),避免小块太碎影响 I/O 效率,也避免太大吃光内存。

关键点:

FileStream
要显式指定
FileMode.Open
FileAccess.Read
,源文件不能被其他进程独占锁定
每个分片文件用
FileMode.Create
,确保覆盖旧碎片
stream.Read(buffer, 0, buffer.Length)
返回值判断是否读到末尾——它可能小于 buffer 长度,不能假设每次读满
别用
File.ReadAllBytes()
StreamReader.ReadToEnd()
,它们会把整个文件塞进内存

分片命名和索引要可预测、可还原

切割后的文件必须能无歧义地合并回原文件,所以命名不能依赖随机数或时间戳(并发或重跑时会冲突)。推荐用序号 + 原文件名前缀 + 固定后缀,比如

archive.zip.001
archive.zip.002

实操建议:

string.Format("{0}.{1:D3}", baseName, index)
保证序号三位对齐,排序时不会出现
.1
.10
.2
这种错序
在首片里额外写一个
.meta
文件(如
archive.zip.meta
),记录总片数、原始大小、校验和(
SHA256
),方便校验完整性
不要把分片扩展名改成
.part
.seg
等自定义后缀——某些系统或工具会忽略它们,直接用
.001
更通用

合并时必须按序读取且严格校验长度

合并不是简单把所有分片

File.AppendAllBytes()
拼起来。如果某片损坏或缺失,后面所有数据都会偏移,最终文件大概率无法打开。

安全做法:

先按命名顺序枚举所有分片文件,用
Directory.GetFiles(dir, $"{baseName}.*")
+ 正则提取序号并排序
每个分片打开为
FileStream
,用
stream.Length
校验是否等于预期大小(最后一片除外)
写入目标文件时,用
outputStream.Write(buffer, 0, bytesRead)
,其中
bytesRead
来自上一步
Read()
的返回值,不是 buffer.Length
合并完成后,计算整个输出文件的
SHA256
并与
.meta
中记录的比对

注意不同场景下的边界处理

真实环境里文件来源复杂:网络流、加密容器、只读介质、UWP 沙盒……这些会影响

FileStream
的构造方式和权限。

常见陷阱:

HttpWebResponse.GetResponseStream()
切割?不行——它不支持
Seek()
,只能顺序读一次,得先落地为临时文件再切
目标路径在 OneDrive 或 WSL 挂载点下?检查
Path.GetFullPath()
是否含非法字符或过长路径(Windows 限制 MAX_PATH=260)
需要支持断点续切?得在临时目录存一个
.progress
文件,记录已写入字节数和当前分片索引,重启时跳过已写完的片
Span<byte></byte>
+
MemoryStream
做缓冲?仅限 .NET Core 3.0+,且仍需注意 Span 生命周期,别把它逃逸到 async 方法外

真正难的不是切,是切完还能稳稳合回去——每一片的字节边界、文件系统行为、异常中断后的状态恢复,都得在代码里显式兜住。

相关推荐