是否有替代方法可以创建跨平台的大型容器文件?

时间:2008-11-03 02:49:14

标签: windows macos cross-platform file-format container-file

以前,我问过question

问题是我们的文件结构要求非常高。

例如,我们正在尝试创建一个包含最多4500个文件和500mb数据的容器。

此容器的文件结构由

组成
  • SQLite DB(1mb以下)
  • 基于文本的xml文件
  • 构成4,500个文件其余部分的动态文件夹结构中的图像

  • 初次创建后,只读取图像文件,但删除除外。

  • 访问容器时会定期使用小型数据库。

Tar,Zip等等都太慢了(即使压缩为0)。我知道,慢是主观的,但要解开这个大小的容器超过20秒。

有什么想法吗?

6 个答案:

答案 0 :(得分:1)

由于您似乎正在对容器执行任意文件系统操作(例如,创建,删除容器中的新文件,覆盖现有文件,追加),我认为您应该选择某种文件系统。分配一个大文件,然后在其中创建一个文件系统结构。

可用的文件系统有多种选择:对于Berkeley UFS和Linux ext2 / ext3,都有可用的用户模式库。您也可能在某处找到FAT实现。确保你理解文件系统的结构,并选择一个允许扩展的 - 我知道ext2很容易扩展(由另一个块组),FAT很难扩展(需要附加到FAT)。

或者,您可以将虚拟磁盘格式放在文件系统下方,允许任意重新映射块。然后,文件系统的“空闲”块不需要出现在磁盘上,您可以分配比实际容器文件大得多的虚拟磁盘。

答案 1 :(得分:0)

假设您只需要对文件进行只读访问,为什么不将它们全部合并在一起并在第二个“索引”文件(或标题中的索引)中告诉您文件名称,起始位置和长度。您需要做的就是寻找起始点并读取正确的字节数。该方法将根据您的语言而有所不同,但大多数方法都非常直接。

最困难的部分就是创建数据文件+索引,甚至这是非常基本的!

答案 2 :(得分:0)

ISO磁盘映像可能会起作用。它应该能够轻松容纳许多文件,并且在所有主要操作系统上都有许多软件支持。

答案 3 :(得分:0)

三件事。

1)Timothy Walters所说的是正确的,我会详细介绍。

2)4500个文件和500Mb的数据只是很多数据和磁盘写入。如果您在整个数据集上运行,那将会很慢。只是I / O真相。

3)正如其他人所说,用例没有详细说明。

如果我们假设一个只读的随机访问场景,那么Timothy所说的几乎已经死了,实现很简单。

简而言之,这就是你所做的。

将所有文件连接到单个blob中。在连接它们时,可以跟踪文件名,文件长度以及文件在blob中启动的偏移量。您将该信息写入一个数据块,按名称排序。我们将其称为目录或TOC块。

然后,将两个文件连接在一起。在简单的情况下,首先是TOC块,然后是数据块。

当您希望从此格式获取数据时,在TOC中搜索文件名,从数据块的开头获取偏移量,添加TOC块大小,并读取FILE_LENGTH个字节的数据。简单。

如果您想要聪明,可以将TOC放在blob文件的END处。然后,在最后追加到TOC开始的偏移量。然后你lseek到文件的末尾,备份4或8个字节(取决于你的数字大小),取这个值,然后再回到你的TOC的开始。然后你回到原点。这样做是为了不必在开始时重建存档两次。

如果您以块为单位布置TOC(比如说大小为1K字节),那么您可以轻松地在TOC上执行二进制搜索。只需用文件信息条目填充每个块,当你用完房间时,写一个标记,用零填充并前进到下一个块。要进行二进制搜索,您已经知道TOC的大小,从中间开始,读取第一个文件名,然后从那里开始。很快,您将找到该块,然后您在块中读取并扫描它以查找该文件。这使得在没有RAM中的整个TOC的情况下有效地进行读取。另一个好处是阻塞需要的磁盘活动少于像TAR这样的链式方案(你必须抓取存档才能找到一些东西)。

我建议您将文件填充到块大小,磁盘就像使用常规大小的数据块一样,这也不困难。

更新此内容而不重建整个内容很困难。如果你想要一个可更新的容器系统,那么你也可以查看一些更简单的文件系统设计,因为那是你在这种情况下真正想要的。

至于可移植性,我建议您按网络顺序存储二进制数,因为大多数标准库都有例程来处理这些细节。

答案 4 :(得分:0)

首先,感谢您扩展您的问题,它为提供更好的答案提供了很多帮助。

鉴于您无论如何都需要一个SQLite数据库,您是否看过将其全部放入数据库的性能?我的经验是基于SQL Server 2000/2005/2008,所以我不肯定SQLite的功能,但我相信它将是查找记录和获取数据的一个非常快的选择,同时仍允许删除和/或更新选项。

通常我不建议将文件放在数据库中,但考虑到4500张图像的所有图像的总大小约为500MB,那么每张图像看起来要超过100K吗?如果您使用动态路径存储图像,那么在稍微更规范化的数据库中,您可以使用“ImagePaths”表将每个路径映射到ID,然后您可以查找具有该PathID的图像并从中加载数据BLOB栏根据需要。

XML文件也可以在SQLite数据库中,它为您的应用程序提供单个“数据文件”,可以在Windows和OSX之间无任何问题地移动。您可以简单地依靠SQLite引擎来提供所需的性能和兼容性。

如何优化它取决于您的使用情况,例如,如果您经常需要在某个路径上获取所有图像,那么具有PathID(作为性能的整数)会很快,但如果您显示全部以“A”开头的图像只是将路径显示为属性,那么ImageName列上的索引将更有用。

我有点担心,虽然这听起来像是过早的优化,因为你真的需要找到一个“足够快”的解决方案,抽象它的机制以便你的应用程序(或者如果你同时拥有Mac和PC的两个应用程序)版本)使用简单的存储库或类似的,然后您可以随意更改存储/检索方法,而不会对您的应用程序产生任何影响。

答案 5 :(得分:0)

检查Solid File System - 这似乎是你需要的。