我一直在使用;DotNetZip";库使用这样的代码:
var files = new []
{
new { file = new FileInfo(@"C:_testDataTestingdata.txt"), source = "Data" },
new { file = new FileInfo(@"C:_testLogsTestingdata.txt"), source = "Logs" },
};
using (Ionic.Zip.ZipFile zipFile = new Ionic.Zip.ZipFile())
{
zipFile.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
foreach (var f in files)
{
zipFile.AddFile(f.file.FullName, f.source);
}
zipFile.Save(@"C:_testoutput.zip");
}
这里需要注意的关键是,文件名是相同的,它们直接包含在具有相同名称的文件夹中,当我创建Zip文件时,我正在为文件创建逻辑文件夹,这样就不会出现文件名冲突。
问题是Zip压缩非常糟糕。事实上,我有一些例子,我放了一堆小文件,得到了一个更大的Zip!
然后我用7-Zip进行了测试,结果非常好。文件大小比Zip小得多。
因此,我尝试使用7-Zip重写我的代码,但似乎没有一个适用于.NET的好的7-Zip库,唯一的选择是通过命令行使用7-Zip。
我在Powershell中尝试过:
."C:Program Files7-Zip7z.exe" a -mx9 "C:_test20210112 Testing.7z" "C:_testDataTestingdata.txt" "C:_testLogsTestingdata.txt"
但我得到了这个输出:
7-Zip 19.00 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2019-02-21
Scanning the drive:
2 files, 40 bytes (1 KiB)
Creating archive: C:_test__test.7z
ERROR:
Duplicate filename on disk:
data.txt
data.txt
如果我添加-spf
命令行,那么它就可以工作了,但我的存档现在是用从C
开始的每个文件夹创建的。
7-Zip中有没有一种方法可以允许它在从命令行添加项目时创建一个逻辑文件夹结构?
需要明确的是,我在文件夹中选择要归档的文件的子集,并希望将它们放在逻辑文件夹中。
如果你只是想压缩文件夹中的所有内容,那么你可以这样做——它将维护文件夹结构。
."C:Program Files7-Zip7z.exe" a -mx9 "C:_test20210112 Testing.7z" "C:_test*"
编辑:要选择性地存档某些文件,请使用相对路径。在您的情况下,您可以将C:_test
设置为当前目录,然后运行
."C:Program Files7-Zip7z.exe" a -mx9 "C:_test20210112 Testing.7z" "DataTestingdata.txt" "LogsTestingdata.txt"
有趣的问题。我经常使用7z,但从来没有需要这样的工作流程。
正如您所知,由于存档中有平面结构的重复文件,您会出现错误。7z
存档程序不知道使用哪一个,因此出现错误。
我想你已经很接近了,但问题是你使用了完全机密的路径来访问要打包的文件。
解决方案
您的解决方案是从C:_test
:运行7z
"C:Program Files7-Zip7z.exe" a -mx9 -spf2 "C:_test20210112_Testing.7z" "DataTestingdata.txt" "LogsTestingdata.txt"
现在,对于相同的文件名,您的归档文件将具有不同的路径。我还建议不要在7z文件名中使用空格-您将来会省去麻烦。如果您有基于输入的相对路径或绝对路径,-spf2
开关将进行调整。如果我需要混合的话,我倾向于把它放在那里。
备注
我喜欢使用-spf2
(不包括完整路径中的驱动器号(开关,因为在操作系统之间切换时,这会让生活更轻松。
7-Zip中有没有方法允许它创建逻辑文件夹从命令行添加项目时的结构?
为了清楚起见,我选择了文件夹中的一个子集存档,我想把它们放在逻辑文件夹中。
不幸的是,不,7-Zip中没有这样的方法。提交人于2015年在他的sourceforge网站上证实了这一点。从那时起,这方面就没有任何更新。
内置的PowerShell cmdletCompress-Archive
也不支持此功能。
您只能通过一个明显的变通方法来实现这一点:临时创建逻辑文件夹结构,将文件复制到其中,归档此临时文件夹结构,然后删除它。如果要保留文件的时间戳(该时间戳将通过常规复制操作进行更改(,则可以将Robocopy.exe
(已内置于Windows中(与/COPY:DAT /DCOPY:DAT
参数结合使用来执行复制操作。
我们从代码中使用SevenZipSharp NuGet包。它有一个CompressFileDictionary功能,可以添加字典中的所有文件,因此您可以选择要添加的文件。
示例:
private void CreateArchive(string archivePath, Dictionary<string, string> materialsToArchive, int part)
{
SevenZip.SevenZipCompressor.SetLibraryPath(Properties.Settings.Default.Location7zDll);
SevenZip.SevenZipCompressor compressor = new SevenZip.SevenZipCompressor()
{
CompressionMode = part == 0 ? SevenZip.CompressionMode.Create : SevenZip.CompressionMode.Append,
ArchiveFormat = SevenZip.OutArchiveFormat.Tar,
CompressionMethod = SevenZip.CompressionMethod.Copy,
CompressionLevel = SevenZip.CompressionLevel.None,
IncludeEmptyDirectories = true,
TempFolderPath = Path.GetDirectoryName(archivePath)
};
compressor.Compressing += new EventHandler<SevenZip.ProgressEventArgs>(CompressorCompressing);
lastPercent = 0;
firstTransfer = true;
compressor.CompressFileDictionary(materialsToArchive, archivePath);
}
字典条目的Key是zip中的相对路径,Value是文件的真实路径。。。