std::filesystem::file_size 是 C++17 及以上获取文件大小最可靠方式,返回 std::uintmax_t 字节数,自动跟随符号链接,无效路径或目录抛 filesystem_error 异常。

用 std::filesystem::file_size 获取文件大小最可靠
在 C++17 及以上,std::filesystem::file_size 是获取文件大小的首选方式,它直接返回 std::uintmax_t 类型的字节数,不依赖平台、不需手动打开文件,也自动处理符号链接(默认跟随)。
常见错误是传入无效路径或目录——它会抛出 std::filesystem::filesystem_error,不是返回 -1 或 0。
- 确保编译器开启 C++17(如
g++ -std=c++17),并包含<filesystem> - Windows 下 MSVC 需链接
shlwapi.lib;GCC/Clang 一般无需额外链接 - 若想获取符号链接本身大小(不跟随),用
std::filesystem::symlink_status(path).size()
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main() {
try {
auto size = fs::file_size("data.bin"); // 抛异常 if not a regular file
std::cout << "size: " << size << " bytes\n";
} catch (const fs::filesystem_error& e) {
std::cerr << "error: " << e.what() << "\n";
}
}
用 std::filesystem::status 和 fs::file_time_type 读取修改时间等属性
文件属性(如最后修改时间、是否为目录、权限位)统一通过 std::filesystem::status 或 symlink_status 获取,返回 fs::file_status 对象,再调用对应方法提取。
注意:status() 默认跟随符号链接,symlink_status() 不跟随;时间精度因平台而异(Linux 通常纳秒,Windows FAT32 只到 2 秒)。
立即学习“C++免费学习笔记(深入)”;
-
fs::last_write_time(path)直接返回fs::file_time_type,可转为time_t用std::chrono::system_clock::to_time_t - 权限判断用
fs::status(path).permissions() & fs::owner_read这类位运算,不是字符串比较 - 判断是否为普通文件:
fs::is_regular_file(status(path)),别用.type() == fs::file_type::regular(类型枚举可能扩展)
兼容旧标准:用 stat() 或 _stat64() 要小心跨平台
如果项目还卡在 C++11/C++14,或者需要细粒度控制(比如硬链接数、设备号),得回退到 POSIX stat()(Linux/macOS)或 Windows _stat64()。两者结构体字段名相似但不完全一致,且 Windows 的 _stat64 不支持 Unicode 路径(需用 _wstat64 + wchar_t*)。
典型坑是:传入相对路径时,stat() 依赖当前工作目录(CWD),而 std::filesystem 总是按绝对或相对于调用点解析,行为更可控。
- Linux/macOS:包含
<sys/stat.h>,用struct stat st; stat("file", &st) - Windows:包含
<sys/stat.h>,用struct _stat64 st; _stat64("file", &st) - 文件大小字段:POSIX 是
st.st_size,Windows 是st.st_size(一致),但注意st_size对目录在某些文件系统上可能不可靠
别用 fseek+ftell 测文件大小
虽然有人用 fopen 打开再 fseek(fp, 0, SEEK_END); ftell(fp),但这有多个硬伤:不支持大于 2GB 的文件(long 溢出)、不能用于设备文件或管道、无法获取修改时间等属性、且必须以二进制模式打开(文本模式在 Windows 会错乱换行符计数)。
除非你明确知道文件小、只读、且已打开句柄(比如从 stdin 重定向来),否则这招纯属倒退。
-
ftell返回long,在 LLP64(如 Windows x64)下最大仅 2GB-1 - 对只读文件系统或 NFS 挂载点,
fseek(... SEEK_END)可能失败或极慢 - 没做
fseek(fp, 0, SEEK_SET)回位就直接读,后续逻辑会出错
stat 和 filesystem 对符号链接的默认行为差异、以及时间戳精度隐含的比较陷阱,最容易被忽略。


















