如何将多个文件夹压缩到一个存档中?

Posted

技术标签:

【中文标题】如何将多个文件夹压缩到一个存档中?【英文标题】:How to compress multiple folders into one archive? 【发布时间】:2013-04-22 21:12:35 【问题描述】:

我有一些压缩组件(如 KAZip、JVCL、zLib)并且完全知道如何使用它们来压缩文件,但是我想将多个文件夹压缩到一个存档中并在提取后保持文件夹结构,我该怎么做?


在所有这些组件中,我只能提供要压缩的文件列表,我不能提供要提取的文件夹结构,没有办法(或者我找不到)告诉每个文件必须在哪里提取:

我在文件夹 FOLDER_A 中有一个名为 myText.txt 的文件,在文件夹 FOLDER_B 中有一个同名的文件 myText.txt:

|  
|__________ FOLDER_A  
|   |________ myText.txt  
|  
|__________ FOLDER_B  
|   |________ myText.txt  
|  

我可以给出要压缩的文件列表:myList(myText.txt, myText.txt) 但我不能给出解压缩文件的结构,找到哪个文件属于哪个文件夹的最佳方法是什么?

【问题讨论】:

你到底想做什么?你在找什么格式。 FWIW 最好的工具是 tpAbbrevia。 问题修改得更清楚,希望如此。 tpAbbrevia 是否支持 UTF 文件名? 好吧,我还是会使用 tpAbbrevia。你真的关心存档的格式吗?这就是我的意思。有很多不同的格式。任何压缩都可以吗? tar+gzip 呢?这对你来说好吗? tpAbbrevia 具有良好的 Unicode 支持。不管怎样,你可以和我一样用谷歌搜索类似的东西。转到 repo,检查一下,然后开始挖掘! delphizip.org 有示例如何做到这一点。此外,我认为您可以拆分枚举文件和压缩文件的任务。一开始你只需要得到你需要的文件列表:docwiki.embarcadero.com/Libraries/XE3/en/… 然后你枚举它们并压缩到docwiki.embarcadero.com/Libraries/XE2/en/… - 你应该从 ArchiveFileName 中去掉“公共”路径的开头。 【参考方案1】:

zip 格式只是没有文件夹。嗯,它有点,但它们是一种空的占位符,只有在你需要像用户访问权限这样的元数据存储时才插入。但除了那些相当罕见的高级东西 - 根本不需要文件夹。真正做了什么——你可以观察到在记事本中打开 zip 文件并滚动到最后——每个文件都有它的路径,从“归档根”开始。在您的示例中,zip 文件应该有两个条目(两个文件):

FOLDER_A/myText.txt FOLDER_B/myText.txt

请注意,使用的分隔符是真正的斜杠,在 UNIX 世界中很常见,而不是在 DOS/Windows 世界中使用的反斜杠。有些库会为您修复反斜杠,有些则不会 - 只做您的测试。

现在,让我们假设该树包含在 D:\TEMP\Project 中 - 仅作为示例。

D:\TEMP\Project\FOLDER_A\myText.txt D:\TEMP\Project\FOLDER_B\myText.txt

还有两个问题(除了路径分隔符):D:\TEMP\Project\ 中是否有更多文件夹应该被忽略,而不是压缩(比如可能是 D:\TEMP\Project\FOLDER_C\*.* ?并且您的 zip 库是否有直接 API 来打包具有内部子文件夹和文件的文件夹,还是应该逐个文件?

在选择库时,您应该问自己并检查这三个问题。代码草稿会有所不同。

现在让我们开始为图书馆本身起草:


默认变体只是使用 Delphi 本身。

    枚举文件夹中的文件:http://docwiki.embarcadero.com/CodeExamples/XE3/en/DirectoriesAndFilesEnumeraion_(Delphi) 如果该枚举结果为absolute paths,则从开头删除常见的D:\TEMP\Project:类似于If AnsiStartsText('D:\TEMP\Project\', filename) then Delete(filename, 1, Length('D:\TEMP\Project\'));。您应该获得相对于所选包含位置的路径。尤其是如果您不压缩整个路径并且将一些 FOLDER_C 保存在存档之外。 也许您还应该调用 StringReplace 将文件名上的“\”更改为“/” 然后你可以使用http://docwiki.embarcadero.com/Libraries/XE2/en/System.Zip.TZipFile.Add 压缩它们 - 注意指定正确的相对ArchiveFileName 就像前面提到的FOLDER_A/myText.txt

您可以使用 ZipMaster 库。它非常受 VCL 约束,可能会导致使用线程或 DLL 出现问题。但对于简单的应用程序,它只是工作。 http://www.delphizip.org/

最新版本页面包含指向“设置”包的链接,其中包含源代码、帮助和演示。在演示中有一个功能齐全的存档浏览器,能够存储文件夹。因此,您可以直接从中读取代码。 http://www.delphizip.org/191/v191.html


您谈到了 JVCL,这意味着您已经安装了 Jedi CodeLib。并且 JCL 带有一个适当的类和函数,根据名称判断也可以直接做你想做的事:function TJclSevenzipCompressArchive.AddDirectory(const PackedName: WideString; const DirName: string = ''; RecurseIntoDir: Boolean = False; AddFilesInDir: Boolean = False): Integer;

实际上,所有这些库在基本级别上都非常相似,当我进行 XLSX 导出时,我只是创建了一个统一的压缩 API,它与实际安装的压缩引擎没有区别。但它适用于内存中的 TStream 而不是磁盘文件,因此不会直接帮助您。但我刚刚了解到,除了地面上的几个怪癖(例如即时与延迟压缩)之外,所有这些库的工作方式都是一样的。

【讨论】:

@Arioch '谢谢,这是有史以来最完整和最详细的答案之一,我尝试了 zipMaster,它有效,但正如你所说的有线程或 DLL 问题,但 JCL 运行良好,没有问题,只需要设置一些运行时设置 @Armin。别客气。也有 WinXP 原生 zip,但代码示例通常用于 VB 或 C#,并将它们翻译成 Delphi 虽然不难,但有点乏味。

以上是关于如何将多个文件夹压缩到一个存档中?的主要内容,如果未能解决你的问题,请参考以下文章

使用 ZipFile 类从多个文件的 zip 存档中解压缩文件

Zip然后将多个文件加密到单个存档中

如何用unzip一次解压多个.zip文件 三种方法

使用 php 将文件添加到 rar 存档

在 Bash 中使用 ZIP 存档

如何使用 CBZip2OutputStream 压缩多个文件