2011-03-06 87 views

回答

1

我想对想要编写自己的实现的解释可能是好奇心。

无论您是否添加压缩,如果您只是想将文件存储在档案中,类似于tar命令,那么您有几种可能的方法。

您必须做出的基本选择之一是:如何划分档案中压缩文件的边界?使用特殊字符并不是一个好主意,因为打包文件可能包含任何开头的字符。

要跟踪文件的结尾,可以使用文件的长度(以字节为单位)。例如,对于每个文件,您可以:

  1. 在档案中写入命名打包文件的'\ 0'终止的C字符串。
  2. 写入存档一个off64_t,它给出打包文件的长度(以字节为单位)。
  3. 将打包文件的实际字节(如果有)写入存档。
  4. (可选)将归档文件的校验和或CRC写入归档。

对每个文件重复执行此操作,并将结果连接起来而不插入字符。

最后,当没有文件时,写一个空的C字符串,一个零字符。

拆包过程是:

  1. 阅读“\ 0'结尾的C字符串,这个名字打包文件。
  2. 如果名称为空,则声明我们已经读取了整个存档,然后退出。
  3. 阅读提供打包文件长度的off64_t。
  4. 从存档中读取与打包文件长度一样多的字节并写入新创建的解压缩文件。

再次重复这些步骤,直到步骤(2)结束程序。

这种设计中文件名与文件数据交替是可行的。它有一些缺点。基本问题是数据结构不是为随机访问而设计的。为了获取档案“中间”的文件信息,需要一个程序来处理前面的文件。程序可以调用lseek_64跳过读取不需要的程序数据,但处理器至少需要读取每个文件名和每个文件长度。文件长度是跳过文件数据所必需的。在我排列数据时,必须读取文件名以查找文件长度。

所以这是低效的。即使不必为了访问文件大小而读取文件名,文件详细信息被分散到整个存档中的事实意味着读取索引数据需要访问磁盘上的多个范围的数据。

更好的方法是将索引数据的“块”写入文件的前面。此数据结构可能类似于:

  1. 存档中第一个文件的大小。
  2. 存档中第一个文件的名称。
  3. 位于此归档中的位置(以字节为单位),其中“第一个文件”可能位于连续的字节块中。
  4. 在归档中的第二个文件的大小...

和索引中的数据可能会重复,直到再次空名称的文件标志着索引的结束。

拥有这样的索引很不错,但会带来一个难题:当用户希望将文件附加到存档时,索引可能需要增加大小。这可能会改变压缩文件在压缩文件中的位置 - 压缩文件可能需要将它们移动以为更大的索引腾出空间。

文件结构可以变得越来越复杂,以满足所有这些不同的需求。例如,可以将索引设计为始终从文件系统认为的“页面”(操作系统从磁盘读取或写入最小大小颗粒的量)中分配索引,并且如果索引需要增长,不连续的“索引页”通过从一个索引页导向另一个索引页的文件位置数据链接在一起。 (就像链接列表一样,但在磁盘上。)复杂性可以继续下去。

0

我一对夫妇一天前写像程序的焦油,在这里我实现(希望你能得到一些想法): 每个文件都存储在文件归档与“头”,这是这样的:

<file-type,file-path,file-size,file-mode> 

在文件类型中,我使用0代表文件,使用1代表目录(通过这种方式,您可以重新创建目录树) 例如,名为foo.txt的文件头大小为245字节,模式为0755 unix,看到chmod)将看起来像:

<0,foo.txt,245,0755> 
here the file contents 

以这种方式,文件存档的第一个字符总是<,然后解析由逗号分隔的列表(第一个可能的错误)并提取文件类型,路径,大小(您将使用它来读取下一个大小字节从档案 - 避免“特殊字符错误”由Heath Hunnicutt指出)和文件的模式(假设你有一个二进制文件,并且你也想在提取它时执行它,你需要用原始文件模式chmod它)。

关于第一个可能的错误,逗号不常用于文件名中,但最好使用另一个字符或“用一对夫妇”消毒路径“”(对不起,我现在不记得名字,而英语不是我的母语),显然解析器应该知道它,并忽略“”中的任何逗号。

对于在C中编写和读取文件,请参阅stdio中的fgetc和fputc。h 要获取文件信息,chmod和目录树可以从sys/stat.h中看到stat和chmod,从ftw.h中看到ftw(可能是linux/unix,因为是系统调用)。

希望它有帮助! (如果你需要一些代码我可以发布一些片段,头文件解析可能是最难的部分)。