假设您有一个想要放入 .zip 存档的文件:
zip a1.zip foo.dll
我的测试 .dll 文件大约 10MB,而存档文件只有 3.5MB
然后创建一个具有完全相同内容的文件,并将这两个文件放入档案中:
cp foo.dll bar.dll
zip a2.zip foo.dll bar.dll
您可能认为 ZIP 足够智能,可以找出重复数据并仅使用 .zip 内的一个压缩对象,但事实并非如此:a2.zip 是 7.0MB!
基本上大多数此类实用程序的行为都类似(tar.gz,tar.bz2,rar处于稳定模式) - 只有 7zip 捕获了我并且生成的 a2.7z 仅比 a1.7z 略大。
所以问题是:是否可以构建一个 .zip 文件来避免这种空间浪费? 我们使用 C++ 代码创建 .zip 文件,该代码使用了来自 zlib 的 minizip 项目。
我们为什么需要这个?
我们以“.exe 安装程序”和“.zip 文件”两种形式提供软件。该软件实际上不需要安装,您只需解压即可使用。拥有许多工作站并使用自动部署/软件更新服务的大型客户更喜欢 .zip 选项。
我们最近引入了三个 .dll 文件,现在需要将它们放在两个不同的文件夹中,以供不同的组件使用(由于技术原因,这些文件无法只放在一个中心目录中)。这三个 .dll 文件在两个文件夹中都是完全相同的副本。.exe 安装程序可以解决这个问题,因为我们指示它对两个目标使用完全相同的压缩 blob。但 .zip 并非如此,最终的安装会大 15MB,这意味着更多的带宽使用、更慢的下载时间和工程师因事情不理想而产生的愤怒。此外,.zip 安装突然变得比 .exe 安装大,所以我们会被问到我们在 .exe 安装中省略了什么。
有一些潜在的解决方案,
- 使用 7-zip:但是老板强烈反对这样做,因为这会迫使前面提到的自动部署人员修改他们的脚本以适应 7-zip。
- 使用符号链接:如果您在 .zip 中放置一个符号链接,该符号链接指向 .zip 中的另一个文件,它将被存储为引用(例如,通过使用选项
--symlinks
)zip
。希望 Win32 下的解压程序能够支持这些,并将文件的副本提取到符号链接所在的路径。虽然 WinRAR 可以做到这一点,但有很多程序“可以执行 .zip”,我不确定是否所有程序都这样做。
答案1
您可以将这两个文件放入一个未压缩的 zip 文件中(例如使用 7-Zip),然后将生成的文件再次放入 zip 文件中。
答案2
您可以通过编写一个小型解压模块来解决问题。您可以将此解压程序分发给用户,以便他们使用它来提取 zip,或者更好的是,将该模块作为 .EXE 程序本身的一部分实现。该模块可以是 C# 控制台程序,如下所示:
private static void Extract(string filename)
{
//ZipInputStream zi = new ZipInputStream (File.Open ("", FileMode.Open));
using (ZipInputStream s = new ZipInputStream(File.OpenRead(filename))) {
ZipEntry theEntry=null;
while ((theEntry = s.GetNextEntry()) != null)
{
Console.WriteLine(theEntry.Name);
string directoryName = Path.GetDirectoryName(basedir + "ext" + Path.DirectorySeparatorChar + theEntry.Name);
string fileName = Path.GetFileName(basedir + "ext" + Path.DirectorySeparatorChar + theEntry.Name);
Console.WriteLine("And the path is:" + basedir + "ext" + Path.DirectorySeparatorChar + theEntry.Name);
// create directory
if ( directoryName.Length > 0 ) {
//Console.WriteLine("DIRECTORY IS SOMETHING");
Directory.CreateDirectory(directoryName);
}
if (fileName != String.Empty) {
using (FileStream streamWriter = File.Create(basedir+"DLL_PATH" + Path.DirectorySeparatorChar + theEntry.Name)) {
int size = 2048;
byte[] data = new byte[2048];
while (true) {
size = s.Read(data, 0, data.Length);
if (size > 0) {
streamWriter.Write(data, 0, size);
} else {
break;
}
}
}
}
}
System.IO.File.Copy("source.dll", "destination.dll"); //IMPORTANT
}
}
这尚未经过测试,但我确信您可以使用它。最重要的部分是将提取的文件复制到新的 dll:
System.IO.File.Copy("source.dll", "destination.dll"); //IMPORTANT
确保将开源 SharpZipLib DLL 包含在内,并且这些是使用的命名空间:
using System;
using ICSharpCode.SharpZipLib;
using ICSharpCode.SharpZipLib.Zip;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
答案3
我提出两种方案:
- 分发自解压文件
.exe
(不是安装程序),它会创建一个目录,其中所有文件都位于正确的相对位置(然后客户端只需将目录拖放到他想要的位置)。如果您使用 7zip 创建它,您将拥有占用空间较小的优势,此外,如果人们安装了 7zip,它可以作为存档由 7zip 本身打开。 - 拥抱简单,坚持
.zip
使用重复文件。带宽真的有那么大的问题吗?用户抱怨东西无法按预期工作/无法执行复杂的安装过程难道不是更大的麻烦吗?从客户的角度来看,这可能不是问题:16 MB 通常不会超过 1 分钟的下载时间,而且他们不必每天都下载相同的文件。当然,这取决于整个安装程序的大小:如果差异在 5 MB 和 21 MB 之间,我也会担心。