gpt4 book ai didi

c - C:创建文件文件头

转载 作者:行者123 更新时间:2023-12-04 22:16:19 27 4
gpt4 key购买 nike

我正在使用C中的POSIX API系统调用来创建文件归档器/提取器(如tar)。我已经完成了部分归档位。

我想知道是否有人可以帮助我使用一些C源代码(在上面使用)为C中的文件创建文件标头(标头充当索引),该标头描述了文件的属性/元数据(名称,日期时间等)。到目前为止,我所做的全部工作是了解(不确定是否正确)创建所需的文件头
一个保存元数据的结构,需要lseek来查找文件的开始/结束
喜欢:


FileName = file.txt FileSize = 0

FileDir =。/ blah / blah

FilePerms = 000

\ n \ n


程序的存档部分具有以下过程:


从命令行获取所有文件的列表。 (我可以做这部分)
创建一个结构来保存有关每个文件的元数据:名称(255个字符),大小(64位int),日期和时间以及权限。
对于每个文件,获取其统计信息。
将每个文件的统计信息存储在结构数组中。
打开存档进行写入。 (我可以做这部分)
编写标题结构。
对于每个文件,将其内容附加到存档文件中(在每个文件的末尾)。
关闭存档文件。 (我可以做这部分)


我很难创建一个整体的头文件,尽管我知道它需要做什么,正如我不能做的位上面的编号点所述(2,3,4,6,7)。

任何帮助将不胜感激。
谢谢。

最佳答案

ijw所述,有几种创建存档文件头的方法。如果跨平台可移植性将成为一个大问题-甚至需要在同一平台上的32位和64位版本的软件之间进行切换-那么,您需要确保以下内容的大小和布局:所有平台上的字段均已完全理解。

每个文件的元数据

一种方法是使用具有已知大小和字节序类型的固定格式二进制标头。这就是ijw建议的。但是,您将需要处理长文件名,因此需要存储一个长度(可能以2字节无符号整数),然后在其后加上实际的路径名。

替代方法(通常是现在最受欢迎的技术)是使用可打印字段(通常称为ASCII格式,尽管这有点用词不当)。时间记录为自从大纪元转换为字符串以来的秒数(以秒为单位)等。这是现代ar档案所使用的;这就是GNU tar所做的(或多或少;有些历史怪癖使这一点更加混乱);这就是cpio -c(通常这几天通常是默认设置)的作用。字段可以用空或空格分隔;有一种简单的方法可以检测标头的结尾;标头包含有关文件名的信息(不一定与您所希望或期望的直接一样,但这通常是因为格式已发展多年),然后是实际数据。以某种方式,您知道每个字段的大小以及标头描述的文件,以便可以可靠地读取数据。

效率是一个红鲱鱼。与第一个磁盘访问相比,向/从文本格式的转换非常迅速,基本上没有可测量的性能问题。而且,保证的可移植性通常远远超过使用二进制数据格式所带来的(微观)性能收益-双重原因是,无论如何,无论如何二进制数据都必须在输入或输出上进行转换以使其成为与体系结构无关的格式。

中央指数与分布式指数

要考虑的另一个问题是归档文件中的文件索引是集中式的(在前端还是在末尾)还是分布式的(每个文件的元数据紧随文件的数据之前)。每种格式都有一些优点-通常,系统使用分布式版本,因为您可以为每个文件编写信息,而无需知道总共要处理多少个文件(例如,因为您递归地归档目录的内容)。预先具有中央索引意味着您可以列出文件而无需阅读整个档案-分布式元数据意味着您必须阅读整个文件。但是,中央索引使存档的构建变得复杂。

请注意,即使使用分布式索引,通常也需要整个存档的标头,以便您可以检测到文件的格式是否符合预期。通常,存在某种标记信息(通常是!<arch>\n存档的ar;在PDF文件的开头等是%PDF-1.2\n,等等)可以确保您的文件包含您所期望的内容。可能会有一些整体(归档级)元数据。然后,您将拥有第一个文件元数据,然后是文件数据,重复进行直到存档结束(可能有也可能没有正式的结束标记-更多元数据)。




[H]现在我可以在您建议的“固定格式二进制标题”中实施它。我在确定需要什么命令/功能时遇到麻烦。


我打算建议您不要使用固定格式的二进制标头;您应该使用基于文本的标题格式。如果您能解决如何使用二进制格式的问题,请成为我的客人(多年来,我已经做过很多次了-这并不意味着我认为这是个好主意)。

因此,这里有一些指向“文本标题”格式的指针。

对于文件元数据,您可以定义包括:


尺寸
模式(权限,类型)
所有者

修改时间
名字的长度
名称


您可能会合理地决定文件大小限制为64位无符号整数,即20个十进制数字。该模式可能以16位八进制数字打印,需要6个八进制数字。所有者和组可能会打印为UID和GID值(而不是名称),在这种情况下,您可以使用10位数字。另外,您可以决定使用名称,但随后应允许每个名称最多32个字符。请注意,名称通常比数字更易于携带。除非您以root身份提取数据,否则名称和编号都与接收机无关紧要(但是为什么要这么做?)。修改时间通常是32位带符号整数,代表自纪元(1970-01-01 00:00:00Z)以来的秒数。您应该允许Y2038错误,方法是允许秒数增长到大于32位的数量。您可能会决定12位前导数字将使您摆脱Y10K危机(大约4倍),这已经足够了;您可能还会决定允许小数秒。在一起,这表明时间戳记的26个空格应该过大。您可以决定每个字段之间用空格隔开(为清晰起见,请考虑“轻松调试”!)。您可能合理地决定所有文件名的总长度限制为4个十进制数字。

您需要知道如何可移植地设置类型的格式-#include <inttypes.h>是您的朋友。

然后,您可以设计一个格式字符串以打印(写入)文件元数据,并设计一个并行字符串以扫描(读取)文件元数据。

印刷:

"%20" PRIu64 " %06o %-.32s %-.32s %26" PRIu64 " %-4d %s\n"


这也会打印名称。它以换行符终止标头。总大小为127个字节加上文件名的长度。这可能太过分了,但是您可以调整数字以适合自己。

扫描:

"%" SCNu64 " %o %.32s %.32s %" SCNu64 "%d"


这不会扫描名称。您需要仔细创建名称扫描程序,这尤其重要,因为您需要读取名称中的空格。实际上,用于扫描用户名和组名的代码也均不包含空格。如果这是不可接受的(也就是说,名称可能包含空格),则您需要更复杂的扫描格式,或者使用 sscanf()以外的其他格式来处理输入数据。

我假设时间字段为64位整数,而不是混合小数秒等,即使有足够的空间允许小数秒。您可能会在这里节省一些空间。

关于c - C:创建文件文件头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4579037/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com