C#编程创建拆分式Zip文件遇阻,求解决方案
解决1.5GB文件夹分卷压缩为100MB Zip块的问题
让我们逐个分析你遇到的问题,然后给出可行的解决方案:
一、各方法失效的原因分析
1. System.IO.Compression 不支持分卷压缩
你说得没错,.NET自带的System.IO.Compression命名空间下的ZipArchive等类确实不支持分卷(拆分)Zip文件。这个类库只提供基础的单文件Zip压缩/解压功能,没有分块输出的实现,所以这个路子走不通是正常的。
2. Ionic.Zip(DotNetZip)生成损坏文件的可能原因
你的代码看起来基本正确,但生成的文件损坏可能有几个点:
- 分卷大小计算错误:
MaxOutputSegmentSize的单位是字节,100MB的正确计算应该是100 * 1024 * 1024 = 104857600字节,而你写的100 * 1000000是100,000,000字节(约95MB),虽然这个不一定导致损坏,但可能不符合你的预期。 - 分卷文件未完整识别:DotNetZip生成的分卷是
test.z01、test.z02...最后是test.zip,你需要把所有分卷文件放在同一目录下,才能用WinZip/WinRAR打开主test.zip文件——如果只单独打开主文件,会提示损坏。 - 库版本或编码问题:确保你用的是最新版的DotNetZip(现在叫
DotNetZip.Reduced),旧版本可能有编码或分卷逻辑的bug;另外,虽然你指定了UTF8编码,但如果文件夹里有特殊字符,可能需要确认编码是否正确适配。 - 路径处理问题:
AddDirectory的第二个参数设为空字符串,会把fonts目录下的所有文件直接放在Zip根目录,这个本身没问题,但如果原目录有嵌套结构,可能导致解压后文件混乱,但一般不会导致损坏。
3. SevenZipSharp(注意:你可能混淆了SharpCompress和SevenZipSharp)代码报错的原因
你提到的SevenZipCompressor其实属于SevenZipSharp库,而非SharpCompress(SharpCompress的API是不同的)。你的代码报错有两个关键点:
- 错误的参数设置方式:SevenZipSharp不需要通过
CustomParameters.Add("v", "100m")来设置分卷,它有专门的VolumeSize属性,直接设置字节数即可。用CustomParameters添加"v"参数会导致参数格式不被识别,触发范围错误。 - 分卷目标路径问题:当设置分卷时,目标路径不能带
.zip后缀——SevenZipSharp会自动生成test.7z.001、test.7z.002这样的分卷文件(如果你指定压缩格式为Zip,会生成test.zip.001等),如果你指定了.zip后缀,会导致路径解析错误。
另外你那段能生成Zip但不拆分的代码,是因为你用了"0", "LZMA2:c=100m"这个参数,这是设置LZMA2的字典大小,不是分卷大小,所以自然不会拆分。
二、可行解决方案
方案1:直接调用7z.exe命令行(最稳妥,已验证可行)
既然你已经确认命令行可以正常工作,那在C#里直接通过Process.Start调用7z.exe是最可靠的方案,避免类库的各种坑。示例代码:
using System.Diagnostics; var sevenZipPath = @"C:\Program Files\7-Zip\7z.exe"; var sourceDir = @"C:\Windows\Fonts"; var targetZip = @"C:\users\me\test.zip"; var arguments = $"a \"{targetZip}\" \"{sourceDir}\" -v100m"; var processStartInfo = new ProcessStartInfo { FileName = sevenZipPath, Arguments = arguments, WindowStyle = ProcessWindowStyle.Hidden, // 隐藏命令行窗口 UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true }; using (var process = Process.Start(processStartInfo)) { process.WaitForExit(); // 可以读取输出和错误信息排查问题 var output = process.StandardOutput.ReadToEnd(); var error = process.StandardError.ReadToEnd(); if (process.ExitCode != 0) { Console.WriteLine($"压缩出错:{error}"); } else { Console.WriteLine("压缩完成"); } }
这个方案完全复用你已经验证过的命令行逻辑,兼容性最好,支持所有7z的参数。
方案2:修复SevenZipSharp的代码
如果你想通过类库实现,正确设置SevenZipSharp的分卷参数即可:
using SevenZip; SevenZipCompressor.SetLibraryPath(@"C:\Program Files\7-Zip\7z.dll"); var compressor = new SevenZipCompressor(); compressor.CompressionMethod = CompressionMethod.Lzma2; compressor.ArchiveFormat = OutArchiveFormat.Zip; // 指定生成Zip格式 compressor.VolumeSize = 100 * 1024 * 1024; // 设置分卷大小为100MB(字节) compressor.CompressDirectory(@"C:\Windows\Fonts", @"C:\users\me\test"); // 目标路径不要加.zip后缀
注意:
- 目标路径不要加
.zip,库会自动生成test.zip.001、test.zip.002...的分卷文件 - 确保你引用的是最新版的SevenZipSharp NuGet包(比如
SevenZipSharp.Net45或对应.NET版本的包)
方案3:修复DotNetZip的代码
如果你坚持用DotNetZip,调整分卷大小并确保分卷文件完整:
using Ionic.Zip; using (var zipFile = new ZipFile(Encoding.UTF8)) { zipFile.AddDirectory(@"C:\Windows\Fonts", directoryPathInArchive: string.Empty); zipFile.MaxOutputSegmentSize = 100 * 1024 * 1024; // 正确的100MB字节数 zipFile.Save(@"C:\users\me\test.zip"); }
生成后,把所有test.z01、test.z02...test.zip放在同一目录,再用WinZip/WinRAR打开test.zip即可正常解压。
内容的提问来源于stack exchange,提问作者John Darvill
相关产品推荐
相关产品推荐

