fopen以"r+b"模式打开失败大概率说明文件正被占用;Windows下只要任意进程以非共享写方式打开文件,该调用即失败并返回nullptr,需结合errno判断EACCES或EBUSY。

用 fopen 以 "r+b" 模式打开失败,大概率说明文件正被占用
Windows 下文件被其他进程以写入或独占方式打开时,fopen 尝试以读写模式("r+b")打开会直接返回 nullptr,这是最轻量、最常用的检测手段。注意不能用 "r" —— 只读模式在多数情况下仍能成功,哪怕文件正被记事本、Excel 等程序打开。
实操建议:
-
"r+b"是关键:它要求操作系统授予读+写权限,而只要任意进程以FILE_SHARE_WRITE以外的方式打开该文件,此调用就会失败 - 必须配合
errno判断:失败后检查errno == EACCES或errno == EBUSY(不同 CRT 实现略有差异),避免把路径不存在等错误误判为“被占用” - 不要依赖
GetLastError():C 运行时封装后,fopen不保证更新 Windows 错误码,应优先信errno
Windows API 的 CreateFile 更精确,但需手动处理共享标志
如果需要区分“被写打开”和“被读打开”,或者想控制超时/重试逻辑,CreateFile 是更底层也更可靠的选择。它的行为由 dwShareMode 参数决定,而不是靠猜测。
实操建议:
- 想检测是否被**任何方式占用**:传
dwShareMode = 0(即不共享),此时只要文件上有任何句柄未关闭,就返回INVALID_HANDLE_VALUE - 想检测是否被**写入占用**:传
dwShareMode = FILE_SHARE_READ,若失败说明有进程以写方式打开(如 Word 正在编辑) - 务必调用
CloseHandle():即使打开失败也要确保不泄漏句柄(虽然失败时返回值不是有效句柄,但成功后忘记关会导致资源累积)
Linux/macOS 下没有“文件占用”概念,open 默认总是成功
Unix-like 系统不阻止对已打开文件的再次打开,open(path, O_RDWR) 几乎总能成功——哪怕目标文件正被 vim 编辑或 tail -f 监听。所谓“被占用”在这里是应用层语义,不是内核级锁。
实操建议:
- 不要指望
open返回错误来判断占用:它只在路径不存在、权限不足、磁盘满等真实异常时失败 - 若需跨进程互斥,改用
flock()或fcntl(F_SETLK)加建议性锁(advisory lock):但这要求所有参与者主动配合,无法检测“顽固进程” - 极端场景下可查
/proc/*/fd/(Linux)或lsof命令输出,但属外部工具依赖,不适合嵌入式或生产环境自动判断
跨平台封装要注意:Windows 和 Unix 行为本质不同,硬统一反而误导
很多跨平台库试图用同一套逻辑封装“检测占用”,结果在 Linux 上永远返回“空闲”,在 Windows 上又因权限/杀毒软件干扰误报。这不是代码写得不够好,而是底层模型不兼容。
实操建议:
- 明确业务需求:你真正要防止的是“写冲突”还是“用户正在编辑”?前者可用原子重命名(
rename())替代覆盖;后者可能更适合检查文件修改时间 + 进程名启发式判断 - 避免封装成
is_file_locked()这类函数:它在不同系统上含义完全不同,调用方容易产生错误预期 - Windows 用
CreateFile+0共享模式;Linux/macOS 放弃“占用检测”,转向“安全写入”策略(如先写临时文件再rename)
真正的难点不在怎么调用某个函数,而在于接受:Windows 的文件句柄独占是强语义,Unix 的文件描述符是弱引用。混用这两套模型,比写错参数更容易出问题。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











