最可靠方法是用stat(),需包含,跨平台统一用st_size字段并检查返回值和S_ISREG;避免ifstream::tellg()等不可靠方式。

直接用 stat() 最可靠,Windows 和 Linux 都支持,但要注意结构体字段名和头文件差异。
stat() 在不同平台的头文件和结构体字段
stat() 是 POSIX 标准函数,Linux/macOS 直接包含 即可;Windows 下需用 MinGW 或 MSVC 的 UCRT 版本(VS2015+),头文件同样是 ,但结构体字段名统一为 st_size —— 不要写成 st_length 或 size,那是错的。
- Linux/macOS:定义在
,struct stat里用st_size - Windows(MSVC/MinGW):同样用
,st_size有效,但st_mode判断文件类型时需用_S_IFREG而非S_IFREG - 别混用
fstat()(需要已打开的 fd)或stat64()(旧兼容接口),除非明确处理超大文件且编译器不默认启用 large file support
stat() 获取大小的最小安全调用模式
必须检查返回值,stat() 失败时不保证 st_size 有定义,直接读会得到垃圾值。常见失败原因包括路径不存在、权限不足、符号链接悬空等。
- 始终判断
stat(path, &sb) == 0,否则跳过或报错 - 建议加一层判断:
if (S_ISREG(sb.st_mode))确保是普通文件,避免把目录、设备文件的st_size当作内容长度 - 示例片段:
struct stat sb;
if (stat("data.bin", &sb) == 0 && S_ISREG(sb.st_mode)) {
off_t size = sb.st_size; // 注意:off_t 是有符号类型,可能为负(极少见)
}
为什么不用 ifstream::tellg() 或 seekg(0, end)?
因为它们不可靠:文本模式下换行符转换会导致偏移失真;某些文件系统(如 NFS)或特殊文件(procfs、FIFO)不支持随机 seek;而且开销大——得真正打开、定位、再关闭。
立即学习“C++免费学习笔记(深入)”;
-
ifstream方式本质是 I/O 操作,stat()是元数据查询,快一个数量级 - 若文件被其他进程截断或扩展,
stat()返回的是当前 inode 的大小,而ifstream::tellg()可能反映打开时的状态(取决于实现) - Windows 上用
GetFileSizeEx()也可行,但跨平台性不如stat()
容易被忽略的细节:off_t 的符号性和对齐
st_size 类型是 off_t,它在 LP64(Linux/x86_64)下是 long int(64 位),但在某些嵌入式平台可能是 32 位。打印时别用 %d 或 %ld 硬套,应使用 PRIdOFF(需 )或转成 uint64_t 后用 %" PRIu64。
- 不要写
printf("%ld", sb.st_size)—— 在 macOS 上可能输出负数(因off_t有符号且高位被误读) - 如果只关心是否 >0,用
sb.st_size > 0安全;若需精确比较大小,确保变量类型匹配 - 注意:C++20 的
std::filesystem::file_size()是更现代的替代,但它底层仍可能调用stat(),且 Windows 上需启用_HAS_FILESYSTEM










