c++如何监控指定文件夹内文件的新增与删除事件记录【实战】

老墨大大_4385

老墨大大_4385

2026-03-31

362人浏览

原创

最轻量方案是Linux用inotify(内核原生,无需第三方库)、Windows用ReadDirectoryChangesW(避免轮询);需注意事件覆盖(如IN_MOVED_TO)、绝对路径、缓冲区大小、跨平台语义差异及调试验证。

c++如何监控指定文件夹内文件的新增与删除事件记录【实战】

Linux 下用 inotify 监控文件夹增删事件最轻量

inotify 是内核原生支持的机制,不依赖第三方库,inotify_init() + inotify_add_watch() 就能监听 IN_CREATE 和 IN_DELETE 两类事件。glibc 已封装好,C++ 直接 #include 即可,不用引入 Boost 或 Qt。

常见错误是只监听 IN_CREATE 却漏掉 IN_MOVED_TO:很多编辑器(如 VS Code、vim)保存文件时用的是“写临时文件 + rename”方式,触发的是移动事件而非创建事件。

  • 必须同时监听 IN_CREATE | IN_DELETE | IN_MOVED_TO | IN_MOVED_FROM 才能覆盖真实场景
  • inotify_add_watch() 的第二个参数是路径,不能是相对路径(会静默失败),必须用 realpath() 转成绝对路径
  • 单次 read() 可能返回多个事件,需循环解析 struct inotify_event,不能假设一次只一个
  • 事件缓冲区大小默认很小(8192 字节),高频操作下容易丢事件;建议 malloc(64 * 1024) 并检查 read() 返回值是否为 -1 且 errno == EAGAIN

Windows 上用 ReadDirectoryChangesW 避免轮询开销

Windows 没有 inotify 对等物,ReadDirectoryChangesW() 是唯一靠谱的异步通知方案。它需要 HANDLE、重叠 I/O 和单独线程处理完成包,比 Linux 复杂,但比每秒 FindFirstFile 轮询强十倍。

典型坑是把 FILE_NOTIFY_CHANGE_FILE_NAME 和 FILE_NOTIFY_CHANGE_DIR_NAME 混用:前者只报文件名变化(新建/删除文件),后者才报子目录变动(新建/删除子目录)。监控文件夹内容,两个标志要 | 运算一起传。

  • 回调函数里拿到的 FILE_NOTIFY_INFORMATION 是变长结构,NextEntryOffset 为 0 表示末尾,不能硬写 for 循环次数
  • 必须用 GetOverlappedResult() 或 IOCP 获取结果,直接 WaitForSingleObject() 容易假死
  • 路径是宽字符,FileNameLength 单位是字节而非字符数,转 std::string 前得先用 WideCharToMultiByte()
  • 该 API 不递归监听子目录,要监控整个树,得对每个子目录单独调用 CreateFile() + ReadDirectoryChangesW()

跨平台封装要注意事件语义差异

Linux inotify 和 Windows ReadDirectoryChangesW 对“删除”的定义不同:inotify 在 unlink() 后立刻发 IN_DELETE,而 Windows 在文件句柄全关闭后才通知——如果某个程序正打开着被删的文件,事件会延迟甚至丢失。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

另一个关键差异是“新增”事件的粒度:IN_CREATE 和 FILE_ACTION_ADDED 都只报告文件名出现,不保证内容已写完。实际业务中常需配合 stat() 或 GetFileSize() 判断文件是否稳定(比如大小不再增长)。

  • 不要在事件回调里直接读新文件——可能读到截断或乱码,加个 usleep(10000) 或用 inotifywait --format '%w%f' -e moved_to,create 做简单验证
  • inotify 的 watch 数量受 /proc/sys/fs/inotify/max_user_watches 限制,默认 8192,监控深目录树前记得 echo 524288 > /proc/sys/fs/inotify/max_user_watches
  • Windows 的 ReadDirectoryChangesW() 缓冲区太小会返回 ERROR_INSUFFICIENT_BUFFER,需动态扩容重试,不能忽略

调试时快速验证事件是否发出

别急着写 C++ 代码,先用系统工具确认内核/OS 层事件确实产生,省去 70% 白忙活。

Linux 下跑 inotifywait -m -e create,delete,move ./target_dir(来自 inotify-tools 包),然后 touch a.txt; rm a.txt,看终端是否实时打印。Windows 下用 PowerShell 的 Get-ChildItem -Recurse | ForEach-Object { $_.FullName } 对比前后快照虽土但有效。

  • 如果 inotifywait 不输出,检查目标路径是否挂载为 noatime 或 tmpfs(部分嵌入式环境不支持)
  • Windows 上若 PowerShell 脚本发现不了变化,先运行 dir /s /b 看是否真有文件,再确认 Explorer 是否卡在刷新状态(它会独占某些句柄)
  • 所有测试务必在目标用户权限下进行:root 创建的文件,普通用户进程可能收不到 inotify 事件;管理员启动的 PowerShell,非管理员 C++ 程序也看不到其触发的变更

事件监听本身不难,难的是边界情况——文件正在被写入、杀进程没关句柄、符号链接绕过监控、容器挂载点行为异常。这些地方没日志、不复现、难定位,得靠提前埋点和对比系统工具输出来卡住问题源头。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
C++ Qt图形开发
C++ Qt图形开发

本专题专注于 C++ Qt框架在图形界面开发中的应用,系统讲解窗口设计、信号与槽机制、界面布局、事件处理、数据库连接与跨平台打包等核心技能,通过多个桌面应用项目实战,帮助学员快速掌握 Qt 框架并独立完成跨平台GUI软件的开发。

2025.08.15

5802

7

C++桌面程序开发
C++桌面程序开发

本专题聚焦 C++ 在桌面端图形界面应用开发中的实战应用,系统讲解 Qt 框架的信号与槽机制、界面布局管理、事件响应、数据交互、样式美化与多窗口应用设计等核心知识。通过实战案例(如记事本应用、数据管理工具、系统监控面板),帮助学习者掌握 从UI设计到完整桌面软件开发的C++工程化能力。

2025.10.23

1514

13

C++ 图形界面开发基础(Qt方向)
C++ 图形界面开发基础(Qt方向)

本专题系统讲解 使用 C++ 与 Qt 进行图形界面(GUI)开发的核心技能,内容涵盖 Qt 项目结构、窗口组件、信号与槽机制、事件处理、布局管理、资源管理,以及跨平台编译与打包流程。通过多个小型桌面应用实战案例,帮助学习者掌握从界面设计到功能实现的完整 GUI 开发能力。

2025.12.05

1441

15

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

7219

3

php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

2025.12.04

818

13

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1829

3

python中的format是什么意思
python中的format是什么意思

python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.06.27

1231

7

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

2023.08.10

4698

6

数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

2023.11.13

3431

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习