使用C# Ionic.Zip压缩C/D盘的排除规则与文件名加密问题
解决方案:C#实现磁盘备份的排除规则与文件名加密
嘿,作为C#新手尝试做磁盘备份确实会遇到这些细节问题,我来帮你一步步解决这两个问题:
问题1:添加排除规则(排除$Recycle.Bin、Windows文件夹及bootmgr文件)
Ionic.Zip(也就是DotNetZip)提供了灵活的过滤机制,你可以在添加目录时通过文件系统信息过滤器来排除指定的文件和目录。核心思路是在AddDirectory方法中传入一个判断委托,决定哪些文件/目录需要被包含。
修改你的代码如下,添加过滤逻辑:
using Ionic.Zip; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace compresszippasswordsplit { class Program { // 定义需要排除的名称集合(不区分大小写) private static readonly HashSet<string> _excludedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "$Recycle.Bin", "Windows", "bootmgr" }; static void Main(string[] args) { BackupDrive("C:\\", @"E:\Allbackups\C-backup"); BackupDrive("D:\\", @"E:\Allbackups\D-backup"); } // 封装备份逻辑,避免重复代码 private static void BackupDrive(string sourceDir, string zipBasePath) { int SizeBackupMB = 10000; string Password = "MysecurePassword"; string ZipLocation = $"{zipBasePath}{DateTime.Now.ToString("-dd-MM-yyyy")}.zip"; using (var zip = new ZipFile()) { zip.Password = Password; zip.Encryption = EncryptionAlgorithm.WinZipAes256; zip.MaxOutputSegmentSize = 1024 * 1024 * SizeBackupMB; // 添加目录并应用过滤规则 zip.AddDirectory(sourceDir, fileSystemInfo => { // 判断当前文件/目录是否在排除列表中 return !_excludedNames.Contains(fileSystemInfo.Name); }); zip.Save(ZipLocation); } } } }
说明:
- 我们把重复的备份逻辑封装成了
BackupDrive方法,让代码更简洁易维护 - 使用
HashSet存储排除名称,并指定StringComparer.OrdinalIgnoreCase来兼容Windows文件系统的大小写不敏感特性 AddDirectory的第二个参数是一个Predicate<FileSystemInfo>委托,返回true表示包含该文件/目录,false表示排除
问题2:实现文件名与文件结构加密
确实,Ionic.Zip只支持加密文件内容,无法加密文件名和压缩包结构。这里提供两种可行的解决方案:
方案1:调用外部WinRAR/7-Zip的命令行工具
WinRAR和7-Zip都支持通过命令行实现加密文件名+分卷备份的功能,你可以在C#中通过Process类调用它们的命令。
示例:调用WinRAR命令行
using System; using System.Diagnostics; namespace compresszippasswordsplit { class Program { static void Main(string[] args) { // WinRAR的安装路径,根据你的实际情况修改 string winRarPath = @"C:\Program Files\WinRAR\WinRAR.exe"; string password = "MysecurePassword"; string dateSuffix = DateTime.Now.ToString("-dd-MM-yyyy"); // 备份C盘 string cSource = @"C:\"; string cDest = $"E:\\Allbackups\\C-backup{dateSuffix}.rar"; string cExclusions = "-x\"C:\\$Recycle.Bin\" -x\"C:\\Windows\" -x\"C:\\bootmgr\""; string cArgs = $"a -r -p{password} -hp{password} -v{10000}m \"{cDest}\" \"{cSource}\" {cExclusions}"; Process.Start(new ProcessStartInfo(winRarPath, cArgs) { CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden }).WaitForExit(); // 备份D盘(逻辑类似) string dSource = @"D:\"; string dDest = $"E:\\Allbackups\\D-backup{dateSuffix}.rar"; string dExclusions = "-x\"D:\\$Recycle.Bin\""; // 根据D盘需要调整排除规则 string dArgs = $"a -r -p{password} -hp{password} -v{10000}m \"{dDest}\" \"{dSource}\" {dExclusions}"; Process.Start(new ProcessStartInfo(winRarPath, dArgs) { CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden }).WaitForExit(); } } }
参数说明:
-a:添加文件到压缩包-r:递归遍历子目录-p{password}:设置文件内容加密密码-hp{password}:设置文件名/结构加密密码(和文件密码可以相同)-v{10000}m:设置分卷大小为10000MB-x{路径}:排除指定的文件/目录
方案2:使用支持文件名加密的C#库(SharpCompress)
如果你不想依赖外部工具,可以使用SharpCompress库,它支持7z格式的完整加密(包括文件名和结构)。
首先通过NuGet安装SharpCompress:Install-Package SharpCompress
然后编写备份代码:
using SharpCompress.Archives.SevenZip; using SharpCompress.Common; using System; using System.IO; namespace compresszippasswordsplit { class Program { private static readonly string[] _excludedNames = new[] { "$Recycle.Bin", "Windows", "bootmgr" }; static void Main(string[] args) { BackupDriveWith7z("C:\\", @"E:\Allbackups\C-backup", "MysecurePassword"); BackupDriveWith7z("D:\\", @"E:\Allbackups\D-backup", "MysecurePassword"); } private static void BackupDriveWith7z(string sourceDir, string zipBasePath, string password) { string dateSuffix = DateTime.Now.ToString("-dd-MM-yyyy"); string destPath = $"{zipBasePath}{dateSuffix}.7z"; long segmentSize = 10000L * 1024 * 1024; // 10000MB using (var archive = SevenZipArchive.Create(destPath, new SevenZipWriterOptions(CompressionLevel.Optimal) { Password = password, EncryptHeaders = true, // 开启文件名/结构加密 SegmentSize = segmentSize })) { // 遍历目录并添加文件,跳过排除项 foreach (var file in Directory.EnumerateFiles(sourceDir, "*", SearchOption.AllDirectories)) { if (ShouldExclude(file, sourceDir)) continue; var relativePath = Path.GetRelativePath(sourceDir, file); archive.AddFile(file, relativePath); } } } private static bool ShouldExclude(string filePath, string rootDir) { var relativePath = Path.GetRelativePath(rootDir, filePath); var parts = relativePath.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries); // 检查当前文件名称或任何父目录名称是否在排除列表中 if (_excludedNames.Contains(Path.GetFileName(filePath), StringComparer.OrdinalIgnoreCase)) return true; foreach (var part in parts) { if (_excludedNames.Contains(part, StringComparer.OrdinalIgnoreCase)) return true; } return false; } } }
说明:
EncryptHeaders = true是开启文件名/结构加密的关键设置- 我们实现了
ShouldExclude方法来递归检查文件的父目录是否在排除列表中,确保完全排除指定项 - SharpCompress支持多种压缩格式,7z是最适合加密需求的选项
内容的提问来源于stack exchange,提问作者danone
相关产品推荐
相关产品推荐

