在符合POSIX标准的C程序中确定二进制常规文件大小的最佳实践

时间:2018-01-17 19:53:21

标签: c posix

我需要确定POSIX下二进制常规文件的文件大小(以字节为单位)。我知道如何在lseek()和fstat()中使用它:

#include <sys/stat.h> // for open() and fstat()
#include <fcntl.h>    // for O_RDONLY
#include <unistd.h>   // for lseek()

int fd = open("something.bin", O_RDONLY);
if (fd == -1)
{
    perror("Unable to open file to read");
    return EXIT_FAILURE;
}

// Using lseek()
const off_t size = lseek(fd, 0, SEEK_END);
if (size == (off_t) -1)
{
    perror("Unable to determine input file size");
    return EXIT_FAILURE;
}
// Don't forget to rewind
if (lseek(fd, 0, SEEK_SET) != 0)
{
    perror("Unable to seek to beginning of input file");
    return EXIT_FAILURE;
}
...

// Using fstat()
struct stat file_stat;
int rc = fstat(fd, &file_stat);
if (rc != 0 || S_ISREG(file_stat.st_mod) == 0)
{
    perror("fstat failed or file is not a regular file");
    return EXIT_FAILURE;
}
const off_t size = file_stat.st_size;

为什么我更喜欢一种解决方案呢?

一种方法是否比另一种方法做得更多(也许是不必要的)?

是否应该首选其他POSIX兼容或标准C解决方案?

2 个答案:

答案 0 :(得分:1)

通常stat(),fstat()将读取文件的元数据以检索用户的文件属性。存储文件元数据的机制可能因文件系统而异,但通常设计为提供最佳的速度/时间复杂度。

'文件大小'是存储在元数据中的文件属性之一,并在各种文件操作(例如写/附加等)时更新。进一步的fstat()不要求你'打开()'文件。

另一方面,如果文件不存在于操作系统的页面缓存中,那么每个'open()'和'lseek()'操作可能会涉及磁盘活动,并且可能会成倍地增加成本。

因此我建议使用fstat()。

答案 1 :(得分:1)

我建议使用stat(2)fstat(2)来获取常规文件的大小(在我看来,文件大小的定义是stat.st_size中的含义} field。。

有些常规文件并不常见。例如,Linux系统上的/proc/self/status/proc/self/maps(阅读proc(5)),即使statls告知它们是“常规文件”。请参阅this

在这样的/proc/伪文件上,没有简单的方法来获得它们的“真实”大小(因为stat(2)告诉0)。

但是,我认为文件大小几乎按照定义,stat(2)告诉你的内容(以及它在/proc/上“撒谎”的事实是恕我直言{{1}文件系统;实际上/proc/的行为几乎与pipe(7)读取结束一样,而不像常规文件。)

还要考虑另一个进程正在更改文件(例如write(2) - 或ftruncate(2) - )的奇怪情况。然后做几个系统调用可能不会很好。

最后,/proc/self/maps是获取文件大小最简单(通常也是最快)的方法。那么为什么还要使用别的东西?