C 是否推荐使用fseek()计算文件大小的方法?

C 是否推荐使用fseek()计算文件大小的方法?,c,file,C,File,在C中,我们可以使用fseek()函数找到文件的大小。像 if (fseek(fp, 0L, SEEK_END) != 0) { // Handle repositioning error } 因此,我有一个问题,这是使用fseek()和ftell()计算文件大小的推荐方法吗?我认为最好的方法是fstat():如果您使用的是Linux或其他类似UNIX的系统,您需要的是stat功能: struct stat statbuf; int rval; rval = stat(path_t

在C中,我们可以使用
fseek()
函数找到文件的大小。像

if (fseek(fp, 0L, SEEK_END) != 0)
{
    //  Handle repositioning error
}

因此,我有一个问题,这是使用
fseek()
ftell()
计算文件大小的推荐方法吗?

我认为最好的方法是
fstat()

如果您使用的是Linux或其他类似UNIX的系统,您需要的是
stat
功能:

struct stat statbuf;
int rval;

rval = stat(path_to_file, &statbuf);
if (rval == -1) {
    perror("stat failed");
} else {
    printf("file size = %lld\n", (long long)statbuf.st_size;
}
在MSVC下的Windows上,您可以使用:


与使用
fseek
不同,此方法不涉及打开或查找文件。它只读取文件元数据。

如果您使用的是Linux或其他类似UNIX的系统,您需要的是
stat
函数:

struct stat statbuf;
int rval;

rval = stat(path_to_file, &statbuf);
if (rval == -1) {
    perror("stat failed");
} else {
    printf("file size = %lld\n", (long long)statbuf.st_size;
}
在MSVC下的Windows上,您可以使用:

与使用
fseek
不同,此方法不涉及打开或查找文件。它只是读取文件元数据。
fseek()/ftell()
有时可以工作

问题

  • 如果文件大小超过大约
    LONG_MAX
    LONG int ftell(文件*流)
    响应有问题

  • 如果以文本模式打开文件,则
    ftell()
    中的返回值可能与文件长度不对应。“对于文本流,其文件位置指示器包含未指定的信息,”C11dr§7.21.9.4.2

  • 如果文件是以二进制模式打开的,
    fseek(fp,0L,SEEK\u END)
    没有很好地定义。“将文件位置指示符设置为文件结尾,就像使用
    fseek(file,0,SEEK_end)
    一样,对于二进制流(由于可能的尾随空字符)或具有状态相关编码的任何流(不一定以初始移位状态结束)具有未定义的行为。”C11dr脚注268。这通常适用于比今天更早的平台,但它仍然是规范的一部分

  • 如果文件是一个类似串行输入的流或
    stdin
    fseek(文件,0,SEEK\u END)
    没有什么意义

  • 查找文件大小的常用解决方案是不可移植的特定于平台的解决方案。这是一个很好的答案

    注意:如果代码试图根据文件大小分配内存,那么文件大小很容易超过可用内存

    由于这些问题,我不推荐这种方法

    通常,应该重新处理问题,使其不需要查找文件大小,而是随着处理更多输入而增加数据


    免责声明:请注意,C规范脚注是信息性的,因此不一定是规范性的。
    fseek()/ftell()
    有时有效

    问题

  • 如果文件大小超过大约
    LONG_MAX
    LONG int ftell(文件*流)
    响应有问题

  • 如果以文本模式打开文件,则
    ftell()
    中的返回值可能与文件长度不对应。“对于文本流,其文件位置指示器包含未指定的信息,”C11dr§7.21.9.4.2

  • 如果文件是以二进制模式打开的,
    fseek(fp,0L,SEEK\u END)
    没有很好地定义。“将文件位置指示符设置为文件结尾,就像使用
    fseek(file,0,SEEK_end)
    一样,对于二进制流(由于可能的尾随空字符)或具有状态相关编码的任何流(不一定以初始移位状态结束)具有未定义的行为。”C11dr脚注268。这通常适用于比今天更早的平台,但它仍然是规范的一部分

  • 如果文件是一个类似串行输入的流或
    stdin
    fseek(文件,0,SEEK\u END)
    没有什么意义

  • 查找文件大小的常用解决方案是不可移植的特定于平台的解决方案。这是一个很好的答案

    注意:如果代码试图根据文件大小分配内存,那么文件大小很容易超过可用内存

    由于这些问题,我不推荐这种方法

    通常,应该重新处理问题,使其不需要查找文件大小,而是随着处理更多输入而增加数据



    免责声明:请注意,C规范脚注是信息性的,因此不一定是规范性的。

    好吧,您可以通过几种方式估计文件的大小:

    • 您可以从头到尾
      读取(2)
      文件,读取的字符数就是文件的大小。这是一种获取文件大小的繁琐方法,因为您必须读取整个文件才能获得大小。但是如果操作系统不允许任意定位文件指针,那么这是获取文件大小的唯一方法
    • 也可以将指针移动到文件末尾的位置。这是您在问题中显示的
      lseek(2)
      ,但是要小心,您必须执行两次系统调用,因为返回的值是将指针移动到所需位置之前的实际位置
    • 或者您可以使用
      stat(2)
      系统调用,该调用将告诉您文件的所有管理信息,如所有者、组、权限、大小、文件在磁盘中占用的块数、文件所属的磁盘、指向该文件的目录项数,这允许您只需一个系统调用即可获得所有这些信息
    您所指出的其他方法(如使用
    ftell(3)
    stdio库调用)也会起作用(同样的问题是,它会导致两个系统调用来设置和检索/恢复文件指针),但可能会涉及一些库,而这些库可能不用于任何其他用途。在
    int
    文件描述符上获取
    FILE*
    指针(例如
    fdopen(3)
    )应该很复杂,只是为了能够在其上使用
    ftell(3)
    函数(两次),然后再次
    fclose(3)
    if (fseek(fp, 0L, SEEK_END) != 0) 
      printf("Size: %ld\n", ftell(fp));
    }