首页 文章

转到C中的二进制文件的某个点(使用fseek),然后从该位置读取(使用fread)

提问于
浏览
6

我想知道这是否是解决问题的最佳方法 .

我知道二进制文件的特定偏移的值,其中我想要的信息被保留...我想要做的是跳转到偏移然后从该位置开始读取一定量的字节 .

在使用谷歌之后,我得出结论,我最好的选择是使用fseek()移动到偏移的位置,然后使用fread()从该位置读取一定量的字节 .

我在想这个是正确的吗?如果是这样,最好怎么做呢?即如何将两者结合在一起 .

如果我不对,你会建议我做什么呢?

非常感谢您的帮助 .

马特

编辑:

我遵循了关于fread()的教程并将其调整为以下内容:

`#include <stdio.h>
    int main()
    {
      FILE *f;
      char buffer[11];
      if (f = fopen("comm_array2.img", "rt"))
      {
        fread(buffer, 1, 10, f);
        buffer[10] = 0;
        fclose(f);
        printf("first 10 characters of the file:\n%s\n", buffer);
      }
      return 0;
    }`

所以我使用文件'comm_array2.img'并从文件中读取前10个字符 .

但据我所知,这是从文件的开始,我想从文件中的某个位置(偏移)

这更有意义吗?

编辑2:

看起来我有点昏暗,所有需要的东西(从我的尝试看起来似乎)是将fseek()放在我在上面的代码中的fread()之前,它寻求到那个位置,然后从那里读 .

3 回答

  • 0

    你的理论听起来很正确打开,寻找,阅读,关闭 .

    为要读取的数据创建一个结构,并将指针传递给struct的已分配内存的read() . 您可能需要在结构上使用#pragma pack(1)或类似内容来防止错位问题 .

  • 2

    它通常取决于您关心的部件之间的距离 . 如果您通常更容易阅读该数据并忽略您所阅读的内容,而不是使用 fseek 来跳过它 . 一种典型的方法是定义一个结构,同时包含您关心的数据,以及您不关心的数据的占位符,在结构中读取,然后只使用您关注的部分:

    struct whatever {
       long a;
       long ignore;
       short b;
    } w;
    
    fread(&w, 1, sizeof(w), some_file);
    
    // use 'w.a' and 'w.b' here.
    

    如果您关心的部件之间有很大的距离,那么您最初使用 fseek 来获取重要部件的想法可能会更简单 .

  • 1

    如果您使用的是文件流而不是文件描述符,那么您可以自己编写一个类似于POSIX pread()系统调用的(简单)函数 .

    您可以使用流而不是文件描述符1轻松模拟它 . 也许你应该自己编写一个这样的函数(它与我在评论中建议的界面略有不同):

    size_t fpread(void *buffer, size_t size, size_t mitems, size_t offset, FILE *fp)
    {
         if (fseek(fp, offset, SEEK_SET) != 0)
             return 0;
         return fread(buffer, size, nitems, fp);
    }
    

    这是 pread()fread() 的约定之间的合理折衷 .


    函数调用的语法是什么样的?例如,从偏移732读取然后再从偏移432读取(均来自文件的开始)和称为f的文件流 .

    因为你没有每次假设100 . 我假设目标变量(缓冲区)是 buffer1buffer2 ,并且它们都足够大 .

    if (fpread(buffer1, 100, 1, 732, f) != 1)
        ...error reading at offset 732...
    if (fpread(buffer2, 100, 1, 432, f) != 1)
        ...error reading at offset 432...
    

    返回计数是每个100字节的完整单元数; 1(得到一切)或0(有些东西出错) .

    还有其他编写代码的方法:

    if (fpread(buffer1, sizeof(char), 100, 732, f) != 100)
        ...error reading at offset 732...
    if (fpread(buffer2, sizeof(char), 100, 432, f) != 100)
        ...error reading at offset 432...
    

    每次读取100个单字节;测试确保您按预期获得所有100个 . 如果您在第二个示例中捕获返回值,则可以知道您获得了多少数据 . 如果第一次读取成功而第二次读取失败,那将是非常令人惊讶的;一些其他程序(或线程)必须在两次调用 fpread() 之间截断文件,但已知有趣的事情发生 .


    1仿效并不完美; pread() 调用提供了保证的原子性,即 fseek()fread() 的组合将不提供 . 但这在实践中很少会成为问题,除非您在尝试定位和读取文件时有多个进程或线程同时更新文件 .

相关问题