我想向二进制文件添加一个结构,但首先我需要检查该文件是否存储了以前的数据,如果没有,我可以添加该结构,否则我必须读取所有存储的数据并粘贴结构在正确的位置,但我对如何检查文件是否为空感到困惑,我考虑尝试这样的事情:
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) ,但随后您采用系统范围的约定,即每个使用该文件的程序都会锁定它。
你可以使用一些database与 ACID特性。查看sqlite或进入RDBMS系统如 PostGreSQL或MariaDB 。或者像 gdbm 这样的索引文件库.
您可以继续编码,隐含的假设(但要注意这一点)只有您的程序正在使用该文件,并且您的程序最多有一个进程在运行它。
if the file is empty [...] how can the file pointer not be
NULL
?
如Increasingly Idiotic answered , fopen
可能会失败,但通常不会在空文件上失败。当然,你需要handle fopen
failure (另见this)。因此,大多数时候,您的 fp
是有效的,并且您的代码块(假设没有其他进程模拟更改该文件)使用 ftell
和 rewind
是检查文件是否为空的近似方法。顺便说一句,如果您从该文件中读取(例如使用 fread
或 fgetc
)某些内容,那么如果您的文件为空,则读取将会失败,因此您可能不需要检查之前是空虚的。
查询某些 fopen
-ed 文件的状态(包括大小)的 POSIX 特定方法是使用 fileno(3)和 fstat(2)在声明 struct stat mystat;
fstat(fileno(fp), &mystat)
一样
关于对使用 ftell() 检查文件是否为空感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50303001/