最直接检测文件是否被占用的方法是用 fopen 尝试打开并检查返回值:若返回 nullptr,再通过 errno(linux/macos)或 getlasterror()(windows)判断失败原因,从而区分“不存在”与“被占用”。

用 fopen 尝试打开文件并检查返回值最直接
Windows 和 Linux 下都没有标准 C++ 接口能“查询”文件是否被占用,只能靠“尝试访问 + 观察失败原因”来间接判断。fopen 是最轻量、跨平台性最好的方式:如果返回 nullptr,再结合 errno(Linux/macOS)或 GetLastError()(Windows)看具体原因,就能区分是“文件不存在”还是“被占用”。
常见错误现象:fopen("test.txt", "r+") 返回 nullptr,但 errno 是 EACCES(权限不足)或 EBUSY(极少见),更常见的是 EPERM(Windows 下实际常映射为 ERROR_SHARING_VIOLATION)。
- 只读打开(
"r")可能成功,即使文件被其他进程以独占写方式打开——因为共享读通常被允许 - 想可靠检测“是否被占用”,必须用带写权限的模式,比如
"r+"或"w"(后者会截断,慎用) - Linux 下多个进程可同时以
O_RDWR打开同一文件,但 Windows 默认启用强制共享检查,所以该方法在 Windows 上更敏感
Windows 下用 CreateFile 获取更精确的占用原因
当需要明确知道“谁占着”或区分“正在写入”和“被记事本打开”,CreateFile 比 fopen 更底层、信息更丰富。它返回句柄而非 FILE*,失败时调用 GetLastError() 可拿到具体错误码。
典型失败场景:CreateFile("data.bin", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr) 中第三个参数 dwShareMode 设为 0(表示不共享任何访问),此时若文件正被其他程序以默认方式打开,就会返回 INVALID_HANDLE_VALUE,且 GetLastError() 为 ERROR_SHARING_VIOLATION。
- 注意不要漏掉
CloseHandle()—— 即使打开失败也要确保没资源泄漏(其实失败时不用关,但逻辑上容易混淆) -
GENERIC_WRITE不一定需要真正写,只是申请写权限;若只想检测,打开后立刻CloseHandle()即可 - 某些程序(如 Excel)会以
FILE_SHARE_DELETE打开文件,此时即使设dwShareMode=0也可能成功——这不是 bug,是对方打开了删除共享
避免轮询:别用 while 循环反复 fopen
看到“文件被占用”就睡 100ms 再试一次?这种轮询写法在服务端或后台工具里很容易引发 CPU 毛刺或响应延迟。真正的“等待释放”应该交给系统通知机制,而不是自己猜。
可行替代方案:
- Linux 下可用
inotify监听IN_MOVED_TO或IN_DELETE_SELF(但注意:文件被占用 ≠ 文件被删,这个只适用于对方关闭后删除的场景) - Windows 下可用
FindFirstChangeNotification或更现代的ReadDirectoryChangesW,监听目录级变化——但同样无法直接通知“某文件解锁了” - 更务实的做法是:首次检测失败后,记录时间戳,后续请求间隔拉长(比如指数退避),并设置最大重试次数
std::filesystem::status 不能判断占用状态
别被名字误导:std::filesystem::status("path") 只查文件是否存在、类型、权限位等元数据,完全不尝试打开文件。它返回 file_status,即使文件正被 Notepad++ 独占打开,只要路径存在、可读,它照样返回 status.type() == file_type::regular。
这是新手最容易踩的坑:以为“能拿到 status 就说明没被占”,结果下一步 ofstream 构造时抛异常或静默失败。
-
std::filesystem::exists()同样无效——它底层调用的就是类似stat()的系统调用,不涉及打开操作 - 唯一能触发 I/O 层面冲突的,是真正执行打开/读写动作的函数,比如
fopen、open、std::fstream::open() - 如果用了
std::fstream,记得检查is_open()或failbit,而不是只看构造是否抛异常(默认不抛)
fwrite 失败后重试或降级策略。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











