一、系统概述
文件分割与合并是数据管理中的基础操作,常用于大文件传输(如邮件附件限制)、分布式存储(拆分后存储至多个介质)、数据备份(分卷压缩)等场景。本工具基于 C# 语言开发,利用 .NET Framework的 System.IO命名空间实现二进制文件流操作,支持按大小分割(如每 1MB/10MB 一个文件)和按序号合并,具备跨平台(Windows/Linux/macOS via .NET Core)、高可靠性(异常捕获、校验机制)和易用性(命令行/GUI 双模式)特点。
二、核心设计思路
2.1 分割策略
- 按固定大小分割 :将源文件拆分为多个指定大小(如
chunkSize = 1024 * 1024字节,即 1MB)的子文件,最后一个子文件可能小于指定大小。 - 文件命名规则 :子文件命名为
原文件名.partN(N 为序号,从 1 开始),如largefile.zip.part1、largefile.zip.part2。 - 元数据记录 (可选):生成
原文件名.info文件,记录源文件大小、分割数量、校验和(如 MD5),用于合并时校验完整性。
2.2 合并策略
- 按序号合并 :读取所有
原文件名.partN子文件,按序号从小到大拼接为完整文件。 - 完整性校验:通过比对子文件数量、总大小或 MD5 校验和,确保合并后文件与源文件一致。
三、实现步骤与代码
3.1 开发环境
- 语言:C# 9.0+
- 框架:.NET 6.0(跨平台支持)
- 工具:Visual Studio 2022 / Visual Studio Code
- 核心类库 :
System.IO(文件流)、System.Security.Cryptography(MD5 校验)
3.2 文件分割实现
3.2.1 核心函数:SplitFile
csharp
using System;
using System.IO;
using System.Security.Cryptography;
public class FileSplitter
{
/// <summary>
/// 分割文件为多个子文件
/// </summary>
/// <param name="sourcePath">源文件路径</param>
/// <param name="outputDir">输出目录(默认当前目录)</param>
/// <param name="chunkSize">子文件大小(字节,默认 1MB)</param>
public static void SplitFile(string sourcePath, string outputDir = ".", long chunkSize = 1024 * 1024)
{
// 校验源文件
if (!File.Exists(sourcePath))
throw new FileNotFoundException("源文件不存在", sourcePath);
// 创建输出目录
Directory.CreateDirectory(outputDir);
string fileName = Path.GetFileNameWithoutExtension(sourcePath);
string fileExt = Path.GetExtension(sourcePath);
string infoPath = Path.Combine(outputDir, $"{fileName}.info");
using (FileStream sourceStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read))
{
long fileSize = sourceStream.Length;
int partCount = (int)Math.Ceiling((double)fileSize / chunkSize);
byte[] buffer = new byte[chunkSize];
// 写入 info 文件(记录元数据)
using (StreamWriter infoWriter = new StreamWriter(infoPath))
{
infoWriter.WriteLine($"SourceFile: {Path.GetFileName(sourcePath)}");
infoWriter.WriteLine($"FileSize: {fileSize}");
infoWriter.WriteLine($"PartCount: {partCount}");
infoWriter.WriteLine($"ChunkSize: {chunkSize}");
infoWriter.WriteLine($"MD5: {CalculateMD5(sourceStream)}"); // 计算源文件 MD5
}
// 分割文件
for (int i = 0; i < partCount; i++)
{
long position = i * chunkSize;
int bytesToRead = (int)Math.Min(chunkSize, fileSize - position);
sourceStream.Seek(position, SeekOrigin.Begin);
int bytesRead = sourceStream.Read(buffer, 0, bytesToRead);
string partPath = Path.Combine(outputDir, $"{fileName}{fileExt}.part{i + 1}");
using (FileStream partStream = new FileStream(partPath, FileMode.Create, FileAccess.Write))
{
partStream.Write(buffer, 0, bytesRead);
}
Console.WriteLine($"已创建: {partPath} ({bytesRead} 字节)");
}
}
Console.WriteLine($"分割完成,共 {partCount} 个子文件,保存至: {outputDir}");
}
// 计算文件 MD5 校验和
private static string CalculateMD5(FileStream stream)
{
using (MD5 md5 = MD5.Create())
{
byte[] hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
}
3.3 文件合并实现
3.3.1 核心函数:MergeFiles
csharp
public class FileMerger
{
/// <summary>
/// 合并子文件为完整文件
/// </summary>
/// <param name="partDir">子文件目录(含 .partN 文件)</param>
/// <param name="outputPath">合并后文件路径</param>
/// <param name="originalName">原文件名(用于匹配子文件,如 "largefile.zip")</param>
public static void MergeFiles(string partDir, string outputPath, string originalName)
{
string fileExt = Path.GetExtension(originalName);
string pattern = $"{Path.GetFileNameWithoutExtension(originalName)}{fileExt}.part*";
string[] partFiles = Directory.GetFiles(partDir, pattern, SearchOption.TopDirectoryOnly);
// 按序号排序(如 part1、part2...)
Array.Sort(partFiles, (a, b) =>
int.Parse(Path.GetFileName(a).Split('.')[0].Substring(originalName.Length + fileExt.Length + 1))
.CompareTo(int.Parse(Path.GetFileName(b).Split('.')[0].Substring(originalName.Length + fileExt.Length + 1)))
);
if (partFiles.Length == 0)
throw new FileNotFoundException("未找到子文件", pattern);
// 合并文件
using (FileStream outputStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write))
{
foreach (string partPath in partFiles)
{
using (FileStream partStream = new FileStream(partPath, FileMode.Open, FileAccess.Read))
{
partStream.CopyTo(outputStream); // 高效复制流
}
Console.WriteLine($"已合并: {partPath}");
}
}
Console.WriteLine($"合并完成: {outputPath}");
}
}
3.4 主程序(命令行交互)
csharp
class Program
{
static void Main(string[] args)
{
Console.WriteLine("C# 文件分割与合并工具");
Console.WriteLine("1. 分割文件");
Console.WriteLine("2. 合并文件");
Console.Write("请选择操作 (1/2): ");
string choice = Console.ReadLine();
try
{
if (choice == "1")
{
Console.Write("源文件路径: ");
string source = Console.ReadLine();
Console.Write("子文件大小 (MB,默认 1): ");
int mb = int.TryParse(Console.ReadLine(), out int m) ? m : 1;
FileSplitter.SplitFile(source, chunkSize: mb * 1024 * 1024);
}
else if (choice == "2")
{
Console.Write("子文件目录: ");
string partDir = Console.ReadLine();
Console.Write("原文件名 (如 largefile.zip): ");
string originalName = Console.ReadLine();
Console.Write("合并后文件路径: ");
string output = Console.ReadLine();
FileMerger.MergeFiles(partDir, output, originalName);
}
else
{
Console.WriteLine("无效选择");
}
}
catch (Exception ex)
{
Console.WriteLine($"错误: {ex.Message}");
}
}
}
参考代码 C#-文件分割与合并 www.youwenfan.com/contentcss/123123.html
四、关键技术点
4.1 二进制流高效处理
- 使用
FileStream的Seek方法定位文件位置,避免全文件加载至内存。 - 通过
CopyTo方法(.NET 4.0+)实现流的高效复制,减少缓冲区操作。
4.2 异常处理与校验
- 文件不存在 :抛出
FileNotFoundException并提示路径。 - 权限不足 :捕获
UnauthorizedAccessException,建议以管理员身份运行。 - MD5 校验 :合并后对比源文件与合并文件的 MD5 值,确保数据一致性(示例中已记录源文件 MD5 至
.info文件)。
4.3 跨平台兼容性
- 使用
Path.Combine处理路径分隔符(\或/),适配 Windows/Linux/macOS。 - 通过 .NET Core 运行时实现跨平台部署(需安装对应 SDK)。
五、扩展功能建议
- 图形界面(GUI):使用 WPF 或 WinForms 开发可视化界面,支持拖拽文件、进度条显示。
- 加密分割:分割时对子文件进行 AES 加密,合并时解密(需密钥管理)。
- 多线程处理:分割/合并时用多线程并行处理子文件,提升大文件操作效率。
- 云存储集成:分割后自动上传子文件至 FTP/SFTP 服务器,合并时从云端下载。