对使用 ftell() 检查文件是否为空感到困惑

标签 c

我想向二进制文件添加一个结构,但首先我需要检查该文件是否存储了以前的数据,如果没有,我可以添加该结构,否则我必须读取所有存储的数据并粘贴结构在正确的位置,但我对如何检查文件是否为空感到困惑,我考虑尝试这样的事情:

size = 0
if(fp!=NULL)
{
    fseek (fp, 0, SEEK_END);
    size = ftell (fp);
    rewind(fp);
}
if (size==0)
{
  // print your error message here
 }

但是如果文件为空或仍未创建,文件指针怎么能不为 NULL 呢?如果我可以简单地做这样的事情,那么使用 ftell() 的意义何在:

if(fp==NULL){fp=fopen("data.bin","wb");

   fwrite(&struct,sizeof(struct),1,ptf);
   fclose(fp);}

我知道在其他情况下可以返回 NULL,例如 protected 文件,但我仍然无法理解当文件为空时文件指针始终返回 NULL 时,使用 ftell() 是如何有效的。帮助将不胜感激:)

最佳答案

i need to check whether the file has previous data stored in it

可能没有可移植且可靠的方法来做到这一点(该文件可能在检查期间发生变化,因为其他进程正在使用它)。例如,在 Unix 或 Linux 上,该文件可能由另一个打开 process当您自己的程序运行时写入它(甚至可能发生在您的 ftell 和您的 rewind 之间)。并且您的程序可能在几个进程中运行。

您可以使用operating system具体功能。对于 POSIX(包括 Linux 和许多 Unix,如 MacOSX 或 Android),您可以使用 stat(2)查询文件状态(包括其大小与st_size)。但之后,某些其他进程可能仍会将数据写入该文件。

您可以考虑咨询 locking ,例如与 flock(2) ,但随后您采用系统范围的约定,即每个使用该文件的程序都会锁定它。

你可以使用一些databaseACID特性。查看sqlite或进入RDBMS系统如 PostGreSQLMariaDB 。或者像 gdbm 这样的索引文件库.

您可以继续编码,隐含的假设(但要注意这一点)只有您的程序正在使用该文件,并且您的程序最多有一个进程在运行它。

if the file is empty [...] how can the file pointer not be NULL ?

Increasingly Idiotic answered , fopen 可能会失败,但通常不会在空文件上失败。当然,你需要handle fopen failure (另见this)。因此,大多数时候,您的 fp 是有效的,并且您的代码块(假设没有其他进程模拟更改该文件)使用 ftellrewind 是检查文件是否为空的近似方法。顺便说一句,如果您从该文件中读取(例如使用 freadfgetc)某些内容,那么如果您的文件为空,则读取将会失败,因此您可能不需要检查之前是空虚的。

查询某些 fopen-ed 文件的状态(包括大小)的 POSIX 特定方法是使用 fileno(3)fstat(2)在声明 struct stat mystat;

后,一起像 fstat(fileno(fp), &mystat) 一样

关于对使用 ftell() 检查文件是否为空感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50303001/

相关文章:

c - 如何从压缩文件(gz)的字节流源获取可读文件描述符

c - 尽管使用数组的字符,但指向整数的指针不兼容

C - float** 函数参数不传递值

在没有sprintf的情况下在C中将整数转换为字符串

c - 在C代码中读取同一个文件两次

c - 消息队列中的 msgtype 成员

c - 为什么第二个 scanf() 不执行

c - 我很难使用引用传递

c - atoi 从字符串到整数使用 char 指针

c++ - 一元类型参数无效 ‘*’