unixc解析文件
我有一个带有头和体的二进制文件格式。标题字段和每个字段的字节数是unixc解析文件,c,file,parsing,unix,C,File,Parsing,Unix,我有一个带有头和体的二进制文件格式。标题字段和每个字段的字节数是 魔法:1 标题大小:2 版本:1 第(共)部分数目:1 节头:节头数量*sizeof(节头) 节头:17+4+4+4 教区名称:17; 剖面类型:4;截面偏移量:4;截面尺寸:4 我需要验证一些限制并打印此文件 version=<version_number> nr_sections=<no_of_sections> section1: <NAME_1> <TYPE_1> <S
version=<version_number>
nr_sections=<no_of_sections>
section1: <NAME_1> <TYPE_1> <SIZE_1>
输出应为:
SUCCESS
version=46
nr_sections=7
section1: fJ00pYisvmveDqS 44 1016
section2: LLSWA0rSmUtSZfRo 44 890
section3: lX9yze6NpWyIifXZ 44 941
section4: de0cLp2V907jC9B 44 1178
section5: JrUrWEEpTJJ5ArY 68 724
section6: Uv707OpGRoR8l9Yen 35 1014
section7: BOWdKpZwrBaahhzz 44 972
(仅包括标题和两个部分)查看您的代码
你的代码有很多错误。让我们看一下:
void parse(const char *path)
{
int fd;
unsigned char c[17];
char name[17];
int type;
off_t size;
fd = open(path, O_RDONLY);
您没有检查对open()
的调用是否成功。如果有错误,fd
将是-1
。一定要检查并妥善处理这个案子
size= lseek(fd,0,SEEK_END);
类似地,lseek()
可以返回错误。某些文件可能不可查找。您可能不必确定文件的大小,请参见下文
lseek(fd,0,SEEK_SET);
for(int i = 0 ; i <=size; i++)
{
这个电话没用!为什么会在这里
read(fd,&c,1);
同样,不检查read()
的返回值。可能存在读取错误,或者文件可能比您想象的小。检查返回值是否不是-1
,而是预期长度(1
)
这看起来像是一次尝试实现。请不要这样做。如果要读取第一个字节并对其进行特殊处理,请不要将其放入for循环中
if(i<5 && c[0]>=')' && c[0]<='C')
printf("version=%d \n", c[0]);
}
在第五个字节之后,for循环只是徒劳地读取字节
lseek(fd,5,SEEK_CUR);
在读取size
字节后,您现在尝试从当前位置再跳过五个字节,这意味着您希望超出文件末尾5个字节
for(int j=1; j<10; j++)
{
再次检查返回值
name[17]='\0';
哎呀,这是缓冲区溢出!您声明name
只有17个字节,现在正在写入第18个字节
read(fd, &type, 4);
您确定类型
足够大,可以容纳4个字节吗?在C语言中,int
具有与平台相关的大小。当然,4字节的int是常见的,但是如果您确实想要4字节的int,最好使用int32\t
printf("section%d: %s %d\n", j + 1, name, type);
由于从j=1开始,因此打印的第一行将从第2节开始:
}
}
建议的前进道路
您应该做的第一件事是尝试正确解析头。确保已从标题中读取节数,因此不需要知道文件大小和/或硬编码任何数字。不要使用lseek()
。在代码处理头之前,不要担心文件的其余部分
一旦正确解析了头的所有元素,就可以开始读取头后面的部分。同样,每个节都有一个头,因此首先要正确解析节头。每个节标题都有一个值,该值指示节的长度和偏移量。将这些存储在一个数组中
既然已经解析了节标题,就可以转到实际数据了。现在,您可能应该开始使用lseek()
转到文件中在节标题中提到的偏移量,然后使用read()
查看节大小的字节数。查看您的代码
你的代码有很多错误。让我们看一下:
void parse(const char *path)
{
int fd;
unsigned char c[17];
char name[17];
int type;
off_t size;
fd = open(path, O_RDONLY);
您没有检查对open()
的调用是否成功。如果有错误,fd
将是-1
。一定要检查并妥善处理这个案子
size= lseek(fd,0,SEEK_END);
类似地,lseek()
可以返回错误。某些文件可能不可查找。您可能不必确定文件的大小,请参见下文
lseek(fd,0,SEEK_SET);
for(int i = 0 ; i <=size; i++)
{
这个电话没用!为什么会在这里
read(fd,&c,1);
同样,不检查read()
的返回值。可能存在读取错误,或者文件可能比您想象的小。检查返回值是否不是-1
,而是预期长度(1
)
这看起来像是一次尝试实现。请不要这样做。如果要读取第一个字节并对其进行特殊处理,请不要将其放入for循环中
if(i<5 && c[0]>=')' && c[0]<='C')
printf("version=%d \n", c[0]);
}
在第五个字节之后,for循环只是徒劳地读取字节
lseek(fd,5,SEEK_CUR);
在读取size
字节后,您现在尝试从当前位置再跳过五个字节,这意味着您希望超出文件末尾5个字节
for(int j=1; j<10; j++)
{
再次检查返回值
name[17]='\0';
哎呀,这是缓冲区溢出!您声明name
只有17个字节,现在正在写入第18个字节
read(fd, &type, 4);
您确定类型
足够大,可以容纳4个字节吗?在C语言中,int
具有与平台相关的大小。当然,4字节的int是常见的,但是如果您确实想要4字节的int,最好使用int32\t
printf("section%d: %s %d\n", j + 1, name, type);
由于从j=1开始,因此打印的第一行将从第2节开始:
}
}
建议的前进道路
您应该做的第一件事是尝试正确解析头。确保已从标题中读取节数,因此不需要知道文件大小和/或硬编码任何数字。不要使用lseek()
。在代码处理头之前,不要担心文件的其余部分
一旦正确解析了头的所有元素,就可以开始读取头后面的部分。同样,每个节都有一个头,因此首先要正确解析节头。每个节标题都有一个值,该值指示节的长度和偏移量。将这些存储在一个数组中
既然已经解析了节标题,就可以转到实际数据了。可能现在您应该开始使用lseek()
转到节标题中提到的文件中的偏移量,然后使用read()
与节大小一样多的字节。as@G。Sliepen已经提到您的代码有许多错误
根据我的评论,您现在已经替换了lseek(fd,5,SEEK_CUR)代码>通过lseek(fd,5,搜索集)代码>
因此