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

我有一个带有头和体的二进制文件格式。标题字段和每个字段的字节数是

  • 魔法: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> <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,搜索集)

    因此