std::filesystem::file_size可直接获取文件大小(字节数),需C++17+、头文件,注意捕获filesystem_error异常,并支持symlink_option::nofollow选项。

用 std::filesystem::file_size 最直接
C++17 起,std::filesystem 提供了标准、跨平台的获取方式。只要路径有效且可访问,std::filesystem::file_size 就返回字节数(std::uintmax_t 类型)。
- 必须包含头文件:
#include,并启用 C++17 或更高标准(如编译时加-std=c++17) - 需处理异常:路径不存在、无权限、是目录而非文件等情况会抛出
std::filesystem::filesystem_error - 注意:对符号链接默认解析目标文件大小;若要获取链接本身元数据,需传入
std::filesystem::symlink_option::nofollow
try {
auto size = std::filesystem::file_size("data.bin");
std::cout << "Size: " << size << " bytes\n";
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Error: " << e.what() << "\n";
}
Windows 下用 GetFileSizeEx 更底层但可控
当需要绕过 std::filesystem 的异常机制,或在旧标准(C++11/14)环境下工作时,Windows API 是可靠选择。
-
GetFileSizeEx返回BOOL,成功时通过LARGE_INTEGER*输出 64 位大小,能正确处理 >4GB 文件 - 必须先用
CreateFile打开文件,且权限至少含GENERIC_READ或FILE_READ_ATTRIBUTES - 别忘了调用
CloseHandle,否则资源泄漏;打开失败时句柄为INVALID_HANDLE_VALUE
HANDLE h = CreateFile(L"input.txt", FILE_READ_ATTRIBUTES,
FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (h != INVALID_HANDLE_VALUE) {
LARGE_INTEGER size;
if (GetFileSizeEx(h, &size)) {
std::cout << "Size: " << size.QuadPart << " bytes\n";
}
CloseHandle(h);
}
POSIX 环境下用 stat 或 fstat
Linux/macOS 等系统中,stat 是最常用方式,尤其适合已知文件路径的场景;若已有打开的文件描述符,则用 fstat 避免重复 open。
-
stat填充struct stat,其中st_size字段即文件字节数(对常规文件有效) - 注意:
st_size对管道、设备文件等可能无意义;对稀疏文件它返回逻辑大小,非磁盘实际占用 - 调用后检查返回值,-1 表示失败(如路径不存在、权限不足),错误码在
errno中
struct stat sb;
if (stat("log.txt", &sb) == 0) {
std::cout << "Size: " << sb.st_size << " bytes\n";
} else {
perror("stat");
}
为什么不用 seekg + tellg?
有人尝试用 std::ifstream 的 seekg(0, std::ios::end) 再 tellg() 来“测长度”,这在多数情况下看似可行,但有明显缺陷:
立即学习“C++免费学习笔记(深入)”;
- 对二进制文件,某些平台(尤其是 Windows)文本模式打开会导致
\r\n转换干扰位置计算 - 流状态可能被其他操作污染(如之前读取失败置位
failbit),tellg()返回 -1 - 不适用于只读不可 seek 的文件(如 FIFO、/proc 文件等),且打开开销比元数据查询大
- 不是原子操作:两次 I/O 调用之间文件可能被截断或扩展
除非你明确在操作一个已打开、可 seek 的流且只关心其当前长度,否则优先用文件系统接口而非流定位。











