在 fseek() 之前保持 FILE 指针的位置

hold position of FILE pointer before fseek()

我正在尝试编写一个 C 函数,它从文件中读取第一行文本,然后使用 fseek()ftell() 来获取文件剩余部分的大小(文件减去第一行)。

我的想法是用第二个FILE *fp1抢到原来FILE *fp的位置,用fseek()fp1送到文件末尾,这样我就不必移动我原来的 fp 并失去它的位置。

这是我的代码。编译器告诉我不能将 fp1 分配给 fp,因为 fp1FILE*fpstruct FILE*

我可以通过这种方式实现我想要做的事情吗?

 FILE *fp, fp1;
 fp = fopen(filename, "r");
 if (!fp)
     return 0;

 fscanf(fp, "%1d", m); //Lines 15-18 read the first line of the file
 fscanf(fp, "%*1c");
 fscanf(fp, "%1d", n);
 fscanf(fp, "%*1c");
 fp1 = fp;         //<---------- This is my problem.
                   //how do I set fp1 to the same place in the
                   //file as fp?

 fseek(fp1, 0, SEEK_END);
 *file_size = ftell(fp1);

这只是将指针复制到文件句柄。正确的方法是在移动之前保存 ftell 结果,并在移动到文件末尾后再次移动回来。

所以:

long saved = ftell(fp);
fseek(fp, 0, SEEK_END);
*file_size = ftell(fp);
fseek(fp, saved, SEEK_SET);

您的定义没有定义 2 FILE * 个指针:

FILE *fp, fp1;

fpFILE *,但 fp1 被定义为 FILE 类型。

您不能以这种方式定义 FILE 对象,它们只能从 fopen() 获得。它们的状态不能通过复制 FILE 对象来保存,它太复杂了,并且除了 FILE 对象之外还使用了其他资源,这可能是一个不完整的类型。

好消息是,您可以使用 ftell() 将当前偏移量保存在 fp 中,然后搜索到末尾以尝试获取文件大小,然后通过另一个调用恢复流位置fseek():

long saved = ftell(fp);
*file_size = -1;  // file size may be impossible to retrieve
if (fseek(fp, 0, SEEK_END) != -1) {
    *file_size = ftell(fp);
}
fseek(fp, saved, SEEK_SET);

但是你要注意这个方法并不靠谱:

  • 不能保证文本文件。
  • 它可能不适用于设备、管道、终端、特殊文件...

您应该尝试修改您的方法,使其不需要知道文件大小。