我必须以这样的方式打包几个文件,以便稍后我可以使用c程序将它们再次打包到原始文件,请提示。
答案 0 :(得分:1)
快速解决方案是利用zLib等外部库(用法示例:http://zlib.net/zlib_how.html)并将其用于压缩。
如果您想更深入地了解压缩主题,请查看不同的无损压缩算法以及Wikipedia - Data compression的进一步提示。
答案 1 :(得分:1)
我认为想要编写自己的实现的解释可能是好奇心。
无论是否添加压缩,如果您只想将文件存储在存档中,类似于tar
命令,那么您可以采用一些方法。
您必须做出的基本选择之一是:如何划分存档中打包文件的边界?使用特殊字符不是一个好主意,因为打包文件可以包含任何开头的字符。
要跟踪文件的结尾,可以使用文件的长度(以字节为单位)。例如,您可以为每个文件:
对每个文件重复执行此操作,连接结果而不插入中间字符。
最后,当没有文件保留时,写一个空的C字符串,一个零字符。
拆包过程是:
再次重复这些步骤,直到步骤(2)结束程序。
这种设计,其中文件名与文件数据交替是可行的。它有一些缺点。基本问题是数据结构不是为随机访问而设计的。为了在归档的“中间”获取有关文件的信息,需要一个程序来处理前面的文件。程序可以调用lseek_64
来跳过读取不需要的程序数据,但处理器需要至少读取每个文件名和每个文件长度。跳过文件数据需要文件长度。必须读取文件名,因为我排列了数据,以便找到文件长度。
所以这是低效的。即使为了访问文件大小而不必读取文件名,文件详细信息在整个存档中都会散布,这意味着读取索引数据需要访问磁盘上的多个数据范围。
更好的方法可能是将索引数据的“块”写入文件的前面。此数据结构可能类似于:
索引中的数据可能会重复,直到具有空名称的文件标记索引的结尾。
拥有这样的索引很不错,但是存在一个难点:当用户希望将文件附加到存档时,索引可能需要增大。这可能会更改存档中打包文件的位置 - 存档程序可能需要移动它们以便为更大的索引腾出空间。
文件结构可以变得越来越复杂,以满足所有这些不同的需求。例如,可以设计索引,使其始终从文件系统认为的“页面”(操作系统从磁盘读取或写入的量作为最小大小的粒度)中分配,并且如果索引需要增长,不连续的“索引页面”通过从一个索引页面到另一个索引页面的文件位置数据链接在一起。 (就像一个链表,但在磁盘上。)复杂性可以继续下去。
答案 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,因为是系统调用)。
希望它有所帮助! (如果你需要一些代码,我可以发布一些片段,标题解析可能是最难的部分。)