最可靠的方法是使用 std::filesystem::status() 获取文件权限并检查 owner_write 位,它跨平台封装了 windows 属性与 linux 权限位的差异,需启用 c++17 并注意路径存在性及异常处理。

用 std::filesystem::status() 检查只读属性最可靠
Windows 和 Linux 对“只读”的语义不同:Windows 把只读当作文件属性(FILE_ATTRIBUTE_READONLY),而 Linux 实际上是看文件权限位(chmod 的 w 位)。C++17 的 std::filesystem 封装了这种差异,直接返回统一的 perms 枚举,比手撸系统 API 更安全、更便携。
实操建议:
- 必须开启 C++17 或更高标准(编译时加
-std=c++17) - 链接时注意:GCC 需要
-lstdc++fs(Clang 10+ 和 MSVC 通常自动处理) - 路径必须存在,否则
status()抛std::filesystem::filesystem_error
try {
auto perms = std::filesystem::status("config.txt").permissions();
bool is_readonly = (perms & std::filesystem::perms::owner_write) == std::filesystem::perms::none;
} catch (const std::filesystem::filesystem_error& e) {
// 处理文件不存在、无访问权等错误
}
Windows 下用 GetFileAttributes() 判断更底层但要注意陷阱
如果你在 Windows 环境下写跨平台兼容性不强的工具,或者需要和旧代码集成,GetFileAttributes() 是常见选择。但它返回的是 Windows 属性掩码,不是权限位 —— 比如对目录也返回 FILE_ATTRIBUTE_READONLY,但这其实不表示“不可写”,只是历史遗留行为。
常见错误现象:
- 误把目录的只读属性当成文件只读(目录的该标志不影响创建子项)
- 没检查返回值是否为
INVALID_FILE_ATTRIBUTES(比如路径不存在或权限不足) - 用
==而非按位与判断:attr & FILE_ATTRIBUTE_READONLY才对
#ifdef _WIN32
DWORD attr = GetFileAttributesA("data.log");
if (attr != INVALID_FILE_ATTRIBUTES &&
(attr & FILE_ATTRIBUTE_DIRECTORY) == 0 &&
(attr & FILE_ATTRIBUTE_READONLY)) {
// 真正的只读文件
}
#endif
Linux/macOS 下别依赖 access(F_OK) 或 stat() 的 st_mode 直接比较
access(path, W_OK) 看似简单,但它检查的是**当前进程的有效 UID/GID 下能否写入**,受 umask、ACL、挂载选项(如 ro)影响,结果可能和文件自身权限位不一致。而直接读 stat().st_mode 又得自己算 uid/gid 匹配逻辑,容易漏掉组权限或其它用户权限。
推荐做法:
- 仍优先走
std::filesystem::status()—— 它在 POSIX 平台内部调用stat()并做正确解析 - 若必须用
stat(),记得用getuid()/getgid()对比st_uid/st_gid,再结合st_mode & 0200(owner write)、& 0020(group write)、& 0002(other write)分别判断 - 避免用
access(path, W_OK)做“静态属性判断”,它反映的是运行时能力,不是文件元数据
只读 ≠ 不能删/重命名,别混淆文件属性和父目录权限
一个常见误解是:“文件只读,我就删不掉它”。实际上,在绝大多数文件系统中,删除或重命名文件由**父目录的写权限**控制,和文件自身的只读属性无关。也就是说,你完全可能删掉一个只读文件,只要对它的所在目录有写权限。
这意味着:
- 仅靠文件只读标志无法实现“防误删”——得限制目录权限或用其它机制(如 chattr +i)
- 判断“能否修改内容”和“能否移动/删除”是两件事,需分别检查文件自身权限和父目录权限
-
std::filesystem::status()只给文件自身的perms,父目录权限得额外调用一次status()查目录路径
真正难搞的点不在怎么读属性,而在理解“只读”到底约束了什么操作——这取决于上下文:是编辑器想禁编辑?备份脚本想跳过?还是部署流程要校验完整性?每个场景要检查的权限层级其实不一样。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











