简体   繁体   English

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

[英]Go to a certain point of a binary file in C (using fseek) and then reading from that location (using fread)

I am wondering if this is the best way to go about solving my problem. 我想知道这是否是解决问题的最佳方法。

I know the values for particular offsets of a binary file where the information I want is held...What I want to do is jump to the offsets and then read a certain amount of bytes, starting from that location. 我知道二进制文件的特定偏移的值,其中我想要的信息被保留...我想要做的是跳转到偏移然后从该位置开始读取一定量的字节。

After using google, I have come to the conclusion that my best bet is to use fseek() to move to the position of the offset, and then to use fread() to read an amount of bytes from that position. 在使用谷歌之后,我得出结论,我最好的选择是使用fseek()移动到偏移的位置,然后使用fread()从该位置读取一定量的字节。

Am I correct in thinking this? 我在想这个是正确的吗? And if so, how is best to go about doing so? 如果是这样,最好怎么做呢? ie how to incorporate the two together. 即如何将两者结合在一起。

If I am not correct, what would you suggest I do instead? 如果我不对,你会建议我做什么呢?

Many thanks in advance for your help. 非常感谢您的帮助。

Matt 马特

Edit : 编辑

I followed a tutorial on fread() and adjusted it to the following: 我遵循了关于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;
    }`

So I used the file 'comm_array2.img' and read the first 10 characters from the file. 所以我使用文件'comm_array2.img'并从文件中读取前10个字符。

But from what I understand of it, this goes from start-of-file, I want to go from some-place-in-file (offset) 但据我所知,这是从文件开始,我想从文件中的某个位置(偏移)

Is this making more sense? 这更有意义吗?

Edit Number 2: 编辑2:

It appears that I was being a bit dim, and all that is needed (it would seem from my attempt) is to put the fseek() before the fread() that I have in the code above, and it seeks to that location and then reads from there. 看起来我有点昏暗,所有需要的东西(从我的尝试看起来似乎)是将fseek()放在我在上面的代码中的fread()之前,它寻求到那个位置和然后从那里读。

If you are using file streams instead of file descriptors, then you can write yourself a (simple) function analogous to the POSIX pread() system call. 如果您使用的是文件流而不是文件描述符,那么您可以自己编写一个类似于POSIX pread()系统调用的(简单)函数。

You can easily emulate it using streams instead of file descriptors 1 . 您可以使用流而不是文件描述符1轻松模拟它。 Perhaps you should write yourself a function such as this (which has a slightly different interface from the one I suggested in a comment): 也许你应该自己编写一个这样的函数(它与我在评论中建议的界面略有不同):

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);
}

This is a reasonable compromise between the conventions of pread() and fread() . 这是pread()fread()约定之间的合理折衷。


What would the syntax of the function call look like? 函数调用的语法是什么样的? For example, reading from the offset 732 and then again from offset 432 (both being from start of the file) and filestream called f . 例如,从偏移732读取然后再从偏移432读取(均来自文件的开始)和称为f的文件流。

Since you didn't say how many bytes to read, I'm going to assume 100 each time. 既然你没有说要读取多少字节,我每次都会假设100个字节。 I'm assuming that the target variables (buffers) are buffer1 and buffer2 , and that they are both big enough. 我假设目标变量(缓冲区)是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...

The return count is the number of complete units of 100 bytes each; 返回计数是每个100字节的完整单元数; either 1 (got everything) or 0 (something went awry). 1(得到一切)或0(有些东西出错)。

There are other ways of writing that code: 还有其他编写代码的方法:

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...

This reads 100 single bytes each time; 每次读取100个单字节; the test ensures you got all 100 of them, as expected. 测试确保您按预期获得所有100个。 If you capture the return value in this second example, you can know how much data you did get. 如果您在第二个示例中捕获返回值,则可以知道您获得了多少数据。 It would be very surprising if the first read succeeded and the second failed; 如果第一次读取成功而第二次读取失败,那将是非常令人惊讶的; some other program (or thread) would have had to truncate the file between the two calls to fpread() , but funnier things have been known to happen. 一些其他程序(或线程)将不得不在两次调用fpread()之间截断文件,但已知有趣的事情发生。


1 The emulation won't be perfect; 1仿效并不完美; the pread() call provides guaranteed atomicity that the combination of fseek() and fread() will not provide. pread()调用提供了fseek()fread()组合不提供的保证原子性。 But that will seldom be a problem in practice, unless you have multiple processes or threads concurrently updating the file while you are trying to position and read from it. 但这在实践中很少会成为问题,除非您在尝试定位和读取文件时有多个进程或线程同时更新文件。

It frequently depends on the distance between the parts you care about. 它通常取决于您关心的部件之间的距离。 If you're only skipping over/ignoring a few bytes between the parts you care about, it's often easier to just read that data and ignore what you read, rather than using fseek to skip past it. 如果你只是在你关心的部分之间跳过/忽略几个字节,那么通常更容易阅读那些数据并忽略你所读的内容,而不是使用fseek跳过它。 A typical way to do this is define a struct holding both the data you care about, and place-holders for the ones you don't care about, read in the struct, and then just use the parts you care about: 一种典型的方法是定义一个结构,同时包含您关心的数据,以及您不关心的数据的占位符,在结构中读取,然后只使用您关注的部分:

struct whatever {
   long a;
   long ignore;
   short b;
} w;

fread(&w, 1, sizeof(w), some_file);

// use 'w.a' and 'w.b' here.

If there's any great distance between the parts you care about, though, chances are that your original idea of using fseek to get to the parts that matter will be simpler. 如果你关心的部件之间有很大的距离,那么你可能最初使用fseek来获得重要部​​件的想法会更简单。

Your theory sounds correct. 你的理论听起来很正确 Open, seek, read, close. 打开,寻找,阅读,关闭。

Create a struct to for the data you want to read and pass a pointer to read() of struct's allocated memory. 为要读取的数据创建一个结构,并将指针传递给struct的已分配内存的read()。 You'll likely need #pragma pack(1) or similar on the struct to prevent misalignment problems. 您可能需要在结构上使用#pragma pack(1)或类似内容来防止错位问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM