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-library 是否有直接 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 而不是磁盘文件,因此不会直接帮助您。但是我刚刚了解到,除了地面上的一些怪癖(例如即时与延迟压缩)之外,所有这些库的工作方式都是一样的。