我需要确定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解决方案?
答案 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)),即使stat
或ls
告知它们是“常规文件”。请参阅this。
在这样的/proc/
伪文件上,没有简单的方法来获得它们的“真实”大小(因为stat(2)告诉0)。
但是,我认为文件大小几乎按照定义,stat(2)告诉你的内容(以及它在/proc/
上“撒谎”的事实是恕我直言{{1}文件系统;实际上/proc/
的行为几乎与pipe(7)读取结束一样,而不像常规文件。)
还要考虑另一个进程正在更改文件(例如write(2) - 或ftruncate(2) - )的奇怪情况。然后做几个系统调用可能不会很好。
最后,/proc/self/maps
是获取文件大小最简单(通常也是最快)的方法。那么为什么还要使用别的东西?