c++oding="utf-8" ?>
windows下用setfileattributes设置只读属性最直接,仅阻止写入而不影响删除或重命名;linux/macos需用chmod配合stat获取并清除三类写权限位;std::filesystem::permissions跨平台存在局限,不推荐依赖。

Windows下用 SetFileAttributes 设置只读属性最直接
在 Windows 平台,C++ 没有跨平台的原生文件权限 API,SetFileAttributes 是最常用、最轻量的方式。它不依赖 C 运行时或 Boost,调用 Win32 API 即可生效。
注意:该函数只影响 NTFS/FAT 文件系统的 FILE_ATTRIBUTE_READONLY 标志,和 Linux 的 chmod 语义不同——它不阻止删除或重命名,仅阻止写入(例如打开写模式会失败)。
- 必须以完整路径调用,相对路径可能因当前工作目录导致失败
- 成功返回非零值,失败时用
GetLastError()查具体错误,常见ERROR_ACCESS_DENIED(权限不足)或ERROR_FILE_NOT_FOUND - 若文件已存在只读属性,再次设置不会报错;想清除只读,需传入其他属性组合(如
FILE_ATTRIBUTE_NORMAL)
#include <windows.h>
bool setReadOnly(const char* path) {
return SetFileAttributesA(path, FILE_ATTRIBUTE_READONLY) != 0;
}</windows.h>
Linux/macOS 用 chmod 修改权限位
POSIX 系统靠权限位控制读写,C++ 需调用 chmod 系统调用。只读意味着移除用户/组/其他三类的写权限(w),通常设为 0444(即 S_IRUSR | S_IRGRP | S_IROTH)。
关键点:权限是按位操作,不是“开关式”设置。直接用 chmod(path, 0444) 会覆盖所有权限,包括执行位——如果原文件有 x,会被清掉。
- 安全做法是先
stat获取当前权限,再用位运算清除S_IWUSR、S_IWGRP、S_IWOTH -
chmod失败常见原因是权限不足(非文件所有者且无 sudo)或路径不存在 - 注意:即使设置了只读,root 用户或文件所有者仍可通过
chmod改回,这和 Windows 的只读属性行为不同
#include <sys>
#include <unistd.h>
bool setReadOnly(const char* path) {
struct stat st;
if (stat(path, &st) != 0) return false;
mode_t new_mode = st.st_mode & ~(S_IWUSR | S_IWGRP | S_IWOTH);
return chmod(path, new_mode) == 0;
}</unistd.h></sys>
跨平台封装要注意 std::filesystem 的局限性
C++17 的 std::filesystem 提供了 permissions 函数,看似能统一处理,但它在只读设置上存在严重限制:
- Windows 下
std::filesystem::permissions(path, perms::owner_write, perm_options::remove)实际调用的就是SetFileAttributes,行为一致 - Linux/macOS 下它只修改用户写权限(
S_IWUSR),忽略组和其他的写位,导致文件对组/其他用户仍可写 - 更麻烦的是:某些旧版 libstdc++(如 GCC 8.3 之前)根本不支持
perm_options::remove,调用会抛std::filesystem::filesystem_error
所以除非你明确只控制 owner 写权限,且能保证编译器和标准库版本支持,否则别依赖它做“真正只读”。
容易被忽略的细节:只读 ≠ 不可删除
无论 Windows 还是 POSIX,文件只读属性本身都不影响删除或重命名操作——这些由父目录的写权限决定。也就是说,一个只读文件,只要所在目录可写,就能被 unlink 或 DeleteFile 删除。
如果业务逻辑真需要防止误删,得额外控制目录权限(Linux)或目录 ACL(Windows),或者改用只读文件系统挂载、进程级文件锁等更高层机制。单纯设文件只读,只是第一道轻量防线。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











