C 将文件指针的位置保持在fseek()之前

C 将文件指针的位置保持在fseek()之前,c,file-io,fseek,C,File Io,Fseek,我正在尝试编写一个C函数,从文件中读取第一行文本,然后使用fseek()和ftell()获取文件其余部分的大小(文件减去第一行) 我的想法是使用第二个文件*fp1来获取原始文件*fp的位置,并使用fseek()将fp1发送到文件末尾,这样我就不必移动原始fp,并失去其位置 这是我的密码。编译器告诉我不能将fp1分配给fp,因为fp1是文件*,fp是结构文件* 我能通过这种方式实现我的目标吗 FILE *fp, fp1; fp = fopen(filename, "r"); if (!fp)

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

我的想法是使用第二个
文件*fp1
来获取原始
文件*fp
的位置,并使用
fseek()
fp1
发送到文件末尾,这样我就不必移动原始
fp
,并失去其位置

这是我的密码。编译器告诉我不能将
fp1
分配给
fp
,因为
fp1
文件*
fp
结构文件*

我能通过这种方式实现我的目标吗

 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);
文件*fp,fp1;
fp=fopen(文件名,“r”);
如果(!fp)
返回0;
fscanf(fp,“%1d”,m)//第15-18行读取文件的第一行
fscanf(fp,“%*1c”);
fscanf(fp,“%1d”,n);
fscanf(fp,“%*1c”);

fp1=fp// 这只是将指针复制到文件句柄。正确的方法是在移动前保存ftell结果,在移动到文件末尾后,再次向后移动

因此:


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

因此:


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

FILE *fp, fp1;
fp
文件*
,但
fp1
被定义为
文件
类型

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

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

但您应该注意,这种方法不可靠:

  • 对于文本文件,这是不保证的
  • 它可能不适用于设备、管道、终端、特殊文件

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

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

FILE *fp, fp1;
fp
文件*
,但
fp1
被定义为
文件
类型

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

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

但您应该注意,这种方法不可靠:

  • 对于文本文件,这是不保证的
  • 它可能不适用于设备、管道、终端、特殊文件

您应该尝试修改您的方法,这样它就不需要知道文件大小。

谢谢您的回复。使用SEEK_SET参数对fseek()的最后一次调用不会将fp重置回文件的开头吗?我试着不那样做。没关系,我看到你已经把储蓄作为一个补偿放进去了。我采纳了你的建议,效果很好。非常感谢你!请注意,此方法不是获取文件大小的可靠方法。它不适用于设备、管道、终端。。。文本文件不保证。谢谢回复。使用SEEK_SET参数对fseek()的最后一次调用不会将fp重置回文件的开头吗?我试着不那样做。没关系,我看到你已经把储蓄作为一个补偿放进去了。我采纳了你的建议,效果很好。非常感谢你!请注意,此方法不是获取文件大小的可靠方法。它不适用于设备、管道、终端。。。对于文本文件,这是不保证的。您可以通过将
fp1
正确声明为指针来修复编译错误-缺少
*
。即
文件*fp,*fp1。但这不是保存文件位置的正确方法(两个指针将引用相同的打开流,因此文件位置相同)。不要发布带有行号的代码,这不方便剪切和粘贴以进行测试。您可以通过将
fp1
正确声明为指针来修复编译错误-缺少
*
。即
文件*fp,*fp1。但这不是保存文件位置的正确方法(两个指针将引用相同的打开流,因此文件位置相同)。不要发布带有行号的代码,这不方便剪切和粘贴以进行测试。我合并了您的错误检查,谢谢。如果我使用C++,我会用CIN。PEEK()来查找EOF,但是我不太精通C。是否使用fOpen-()保持类似的EOF标记?我想我关于这方面的进一步问题不一定是这个问题的一部分。
fopen
不维护eof标志。在C语言中,通过尝试读取
文件*
,您才知道自己处于流的末尾。您可以这样写:
intpeek(FILE*fp){intc=getc(fp);if(c!=EOF)ungetc(c,fp);返回c;}
并使用
if(peek(fp)==EOF)
作为文件结尾的测试。我合并了您的错误检查,谢谢。如果我使用C++,我会用CIN。PEEK()来查找EOF,但是我不太精通C。是否使用fOpen-()保持类似的EOF标记?我想我关于这方面的进一步问题不一定是这个问题的一部分。
fopen
不维护eof标志。在C中,您可以继续
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);