使用c打包文件,以便可以解压缩到原始文件

时间:2011-03-06 15:22:41

标签: c

我必须以这样的方式打包几个文件,以便稍后我可以使用c程序将它们再次打包到原始文件,请提示。

3 个答案:

答案 0 :(得分:1)

快速解决方案是利用zLib等外部库(用法示例:http://zlib.net/zlib_how.html)并将其用于压缩。

如果您想更深入地了解压缩主题,请查看不同的无损压缩算法以及Wikipedia - Data compression的进一步提示。

答案 1 :(得分:1)

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

无论是否添加压缩,如果您只想将文件存储在存档中,类似于tar命令,那么您可以采用一些方法。

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

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

  1. 将归档的'\ 0'终止的C字符串写入存档,该字符串命名打包文件。
  2. 向存档写入off64_t,它给出打包文件的长度(以字节为单位)。
  3. 将归档文件的实际字节(如果有)写入存档。
  4. (可选)将归档文件的校验和或CRC写入归档文件。
  5. 对每个文件重复执行此操作,连接结果而不插入中间字符。

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

    拆包过程是:

    1. 读取'\ 0'终止的C字符串,该字符串命名此打包文件。
    2. 如果名称为空,请断言我们已阅读整个档案,然后退出。
    3. 读取off64_t,它给出了打包文件的长度。
    4. 从存档中读取与打包文件长度一样多的字节,并写入新创建的解压缩文件。
    5. 再次重复这些步骤,直到步骤(2)结束程序。

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

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

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

      1. 存档中第一个文件的大小。
      2. 存档中第一个文件的名称。
      3. 此存档中的位置(以字节为单位),其中“第一个文件”可能位于连续的字节块中。
      4. 存档中第二个文件的大小......
      5. 索引中的数据可能会重复,直到具有空名称的文件标记索引的结尾。

        拥有这样的索引很不错,但是存在一个难点:当用户希望将文件附加到存档时,索引可能需要增大。这可能会更改存档中打包文件的位置 - 存档程序可能需要移动它们以便为更大的索引腾出空间。

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

答案 2 :(得分:0)

我几天前写了一个tar程序,这里是我的实现(希望你能得到一些想法): 每个文件都存储在文件存档中,带有“标题”,如:

<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

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

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

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

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