我有一个程序可以处理由多个文件组成的项目。 每个项目都保存在同名的文件夹中,其中包含同名的项目文件,以及一个或多个支持文件。
C:\...\Projects\Project01\
C:\...\Projects\Project01\project01.prj
C:\...\Projects\Project01\support-a.xyz
C:\...\Projects\Project01\support-b.xyz
C:\...\Projects\Project01\Sub\afile.xyz
现在我希望能够将项目文件夹压缩到同名的 zip 存档中:
C:\...\Projects\Project01.zip
我希望我的程序能够访问存档中的文件,就像它们是文件夹中的文件一样。 问题是文件系统不处理将 zip 文件的位置与 zip 文件内 ZipArchiveEntry 的相对路径相结合的路径,例如C:\Temp\ProjectsProject01.zip\子文件.xyz。 您无法使用这样的路径创建 FileStream。 我可以使用函数来检测路径中的存档,然后使用 ZipArchive.GetEntry().Open() 或 FileStream 返回流。 但问题远不止于此。 我现有的代码也使用 FileInfo,但这也不适用于这些混合路径。
我认为我有两个选择,要么添加一堆逻辑来正确处理这两种情况,要么我可以设计 System.IO.Abstractions 中类型的实现来透明地处理这个问题,委托给文件系统或 ZipArchive 类作为需要。 但我想知道我是否遗漏了一些这不起作用的根本原因,例如同时访问存档中的多个文件的问题,何时处置存档等。我怀疑如果这可行,它就已经是完毕。 但事实是 Windows 资源管理器似乎实现了这种行为,这让我想知道为什么它在 System.IO 中不可用。
Windows API 函数及其 .NET 包装器
Windows 中的文件系统需要内核模式驱动程序。标准驱动程序(例如 NTFS 或 FAT 驱动程序)仅提供相应的格式。他们不知道如何将复合容器表示为目录。
要将目录“注入”到现有文件系统中,您可以使用以下技术之一:
以上只是驱动相关的部分。您还需要文件系统逻辑的实际实现(这里,“文件系统”不是像 NTFS 或 FAT 那样的磁盘布局,而是根据操作系统和驱动程序的请求管理一组文件和目录的规则) 。当然可以将 ZIP 文件呈现为文件系统;然而,它的格式主要适用于只读文件系统。即,将 ZIP 呈现为只读文件系统比支持更新容易得多。原因是文件系统的实现需要随机访问文件数据(也用于写入)以及添加和删除文件的能力。 ZIP格式不容易支持这些类型的操作;修改文件时,您必须重新写入 ZIP 存档的大块内容。
文件资源管理器,为了支持 ZIP 和其他格式,实现了称为“Shell 命名空间扩展”的 Shell 技术。该技术受到 Shell 的限制,即,注入 Shell 命名空间的任何内容都只能通过 Shell API 函数和接口访问。与文件系统相关的 Windows 函数不适用于该命名空间。
考虑到上述所有内容,寻找已包含驱动程序并支持 ZIP 格式的解决方案是合理的。
如果您不需要特定的文件格式 (ZIP),我们有一个有趣的解决方案,名为 CBFS Storage(也是一个组件库),它提供了一个数据容器,您可以将其安装到驱动器号或连接点。它不受 ZIP 的限制,并且具有内置的压缩和加密支持。该产品也是基于驱动程序的,其驱动程序实现了 SolFS,这是我们已经开发了 20 多年的文件系统。您可以将容器文件(保管库)作为常规文件(类似于 ZIP)保留在磁盘上,或者可以使用 MemoryVault 组件来创建内存磁盘。