001-监控你的文件-FSWatch-C++开源库108杰

news2025/3/12 19:06:29
  1. fswatch 原理与应用简介
  2. fswatch 安装
  3. fswatch 实践应用
  4. 具体应用场景与细节补充

在这里插入图片描述

1. 简介

有些知识,你知道了不算厉害,但你要是不知道,就容易出乱。

很多时候,程序需要及时获取磁盘上某个文件对象(文件夹、文件)的变动信息,这时候 “绝大多数操作系统支持主动推送此类信息” 这个知识点,就很重要。

如果不知道这点,大概就只能让程序定时去检查、并维护前后两套数据,自行对比以发现是否有哪个文件对象发生了哪些变化。

fswatch 本是多数 linux 下的一个工具程序——但现已经支持跨平台。它提供动态库和配套的 C、C++头文件 (合称为 libfswatch),借助它,我们也可以在自己的程序中,直接获得监控指定文件对象变动信息。

更多关于文件变动信息监控以及 libfswatch 库的基本原理、功能以及应用场景示例,请看视频 A。

  • 视频 A : FSWatch 简介

001-监控你的文件-1原理简介-C++开源库108杰

2. 安装 fswatch

Linux 下,可以使用各自发行版自带的包管理器安装 fswatch。以 Ubuntu 为例:

sudo apt install fswatch

Windows下,因为我们使用 msys2 来安装 fswatch。进入对应环境(我们的课程使用的是 ucrt64)的终端,输入以下指令即可:

pacman -S mingw-w64-ucrt-x86_64-fswatch

msys2 本身的安装可看课程 《VSCODE 多语言开发保姆手册》)的第一节课 《MSys2 + GCC 安装与应用》。

如果你手快并且长得帅的话,最快十秒钟具体操作过程以及效果演示,见视频 B 。

002-监控你的文件-2十秒安装-C++开源库108杰

3. 上机实践

我们使用 Windows + Msys2 + VSCode + GCC + CMake 的开发环境,相关准备工作同样可观看 《VSCODE 多语言开发保姆手册》)。

  • 视频 C: 上机实践

003-监控你的文件-3使用示范-C++开源库108杰

3.1 CMakeList.txt

cmake_minimum_required(VERSION 3.15.0)
project(HelloFSWatch VERSION 0.1.0 LANGUAGES C CXX)

add_executable(HelloFSWatch main.cpp)

target_link_libraries(${PROJECT_NAME} PRIVATE fswatch) 
target_link_directories(${PROJECT_NAME} PRIVATE "C:/msys64/ucrt64/bin")

说明:

其中最后两行是我们添加的。

  • 第一行 target_link_libraries 用于告诉编译器,当前项目需要链接到 fswatch 这个库;
  • 第二行 target_link_directories 则告诉编译器,上哪里去找 fswatch 这个库;
  • PRIVATE 用于指示对应的设置,仅在当前目标中生效,对我们这个小项目并无影响;
  • ${PROJECT_NAME} 是 CMake 的内置变量,用于表示当前项目名称,即 HelloFSWatch (见第2行的 project 语句)

GCC 在链接某个库时,会自动为它加上 lib 前缀,以及对应的扩展名,本例为 .dll,因此,我们在 CMake 源文件中写的 fswatch,最终会组成全名 “libfswatch.dll”

3.2 main.cpp

#include <ctime>

#include <iostream>
#include <iomanip>

#include <libfswatch/c++/monitor_factory.hpp>

// 返回值:必须是 void,入参必须是 std::vector<fsw::event> const & 和 void *
void on_file_changed(std::vector<fsw::event> const & events, void *)
{
    std::cout << "Files Changed:\n";

    for (auto const& event : events)
    {
        // 输出变动的文件路径:
        std::cout << event.get_path() << "\n";
        
        // 输出变动的时间:
        std::time_t t = event.get_time();
        std::tm lt; // local time 本地时间结构
        localtime_s(&lt, &t); // C11 开始支持的线程安全的时间转换函数

        std::cout << std::put_time(&lt, "%Y-%m-%d %H:%M:%S") << "\n";

        // 输出变动的标志:
        std::cout << "Flags:\n";
        for (auto const& flag : event.get_flags())
        {
            std::cout << "\t" << fsw_get_event_flag_name(flag) << "\n";
        }
    }
}

int main(int, char**) 
{
    std::vector<std::string> paths = {"d:\\tmp"};

    auto *monitor = fsw::monitor_factory::create_monitor(
        system_default_monitor_type,
        paths,
        on_file_changed
    );

    // 启动监控
    monitor->start();  // 进入死循环
}

如代码所示,使用 fswatch 实现被动式响应(那操作系统主动回调我们的函数)的文件变动监控过程,关键三步:

Step1 : 通过工厂类的静态方法 create_monitor 创建一个监控器。需指定类型(通常就是采用代码中的默认类型)、待监控的文件对象路径(默认类型下,Windows 操作系统仅支持以文件夹为单位进行测控,因此该参数只能填写文件夹),回调函数;实际还有第四个默认参数,用于向回调函数传递额外的参数,通常并不需要,因此它有默认值 nullptr;

Step2 : 准备好你的回调函数(即代码中的 on_file_changed ),注意,该函数原型须严格符合:void (std::vectorfsw::event const& , void *) ;

Step3 : 启动监控。

3.3 on_file_changed 详解

回调函数名字无所谓。第一个入参类型需为 std::vectorfsw::event const& ,这是一个常量引用,第二个入参为 void *,即前面创建监控器,所传入的第四个参数(我们使用的了函数参数默认值)。

第一个入参 events 是复数(一个容器),表明该函数被操作系统回调用时,操作系统可能想告诉我们的情况有可能是:

  • 一个文件对象的一个变动事件;
  • 一个文件对象的多个变动事件;
  • 多个文件对象的多个变动事件。

每一个 event 主要包含:变动文件路径的对象(如果变动对象是一个文件,此时Windows系统上报的也是文件名),变动时间(注意,不一定非常精确),变动标志等。

库为变动标志取了一些英文名字,常见的有:

  • NoOp : 无变动
  • PlatformSpecifc :特定平台指定
  • Created
  • Updated
  • Removed
  • OwnerModified : 对象的拥有者变化,常见于 *uix 系统;
  • AttributeModified: 对象属性发生变化
  • MovedFrom
  • MovedTo
  • ……

每个变动事件可能包含有多个变动标志。

on_file_changed 第一层循环用来遍历所有事件,输出每个对象变动路径、时间。其中用到 纯C(不要加 std::)的,C11 才支持安全的时间转换函数 localtime_s 和 C++ 输出的扩展的格式操控符:put_time() 注意操控符并不返回字符串。

有关 C++ 流与操控符(比如,如何自定义一个输入或输出流操控符),可学习 《C++“流”编程视频辅导》。

第二层循环输出当前事件的所有标志,其中用到 fsw_get_event_flag_name()以获取指定标志值对应的英文名称。

4. 补充

4.1 场景补充

许多问题,确实可以通过这个“消息队列”轻松实现,除视频中提到的给用户发送通知邮件之外,还有如下场景可考虑使用:

  • 用户上传文件内容审核:某网站系统,允许用户发表带图的文章,需要对图片或文章的文字内容做安全审核;
  • 线上系统自动源代码编译:程序员使用 git 等工具,将相关模块的源代码上传到服务器上并触发自动编译;
  • 数据采集与比对系统:为了稳定性,很多监控系统会划分成数据采集与数据比对两个独立的子进程。

4.2 细节补充

“封包” 文件:很多时候,接收方发现出现一个新增的文件,并不能直接开始读取它,因为此时发送方可能还在往该文件中写入数据。此时有两种经典解决方法。

  • 方法一:要求发送方以独占模式打开文件,对应的,接收方尝试也以独占模式打开,这样后者将失败,从而避免双方同时处理(哪怕一写一读);
  • 方法二:双方约定特定文件名称(通常是扩展名)为 “封包”文件。比如,约定 .seal为封包文件的扩展名。则当发送方先生成 a.dat 文件,再生成名为 a.dat.seal 的封包文件(通常是一个零字节文件);接收方仅在发现后者之后,才开始处理 a.dat(并在处理结束后,删除封包文件)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2299883.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringMVC环境搭建

文章目录 1.模块创建1.创建一个webapp的maven项目2.目录结构 2.代码1.HomeController.java2.home.jsp3.applicationContext.xml Spring配置文件4.spring-mvc.xml SpringMVC配置文件5.web.xml 配置中央控制器以及Spring和SpringMVC配置文件的路径6.index.jsp 3.配置Tomcat1.配置…

ESXi安装【真机和虚拟机】(超详细)

项目简介&#xff1a; ESXi&#xff08;Elastic Sky X Integrated&#xff09;是VMware公司开发的一种裸机虚拟化管理程序&#xff0c;允许用户在单一物理服务器上运行多个虚拟机&#xff08;VM&#xff09;。它直接安装在服务器硬件上&#xff0c;而不是操作系统之上&#xff…

学习笔记之debian的thonny开发(尚未验证)--从stm32裸机到linux嵌入式系统

这应该算 stm32裸机用户 转 linux嵌入式系统 的入门学习笔记。 【鲁班猫】39-vnc远程桌面连接鲁班猫_哔哩哔哩_bilibili 本集的鲁班猫的视频介绍中&#xff0c;没有清晰明确指出需要linux开发板接入网络&#xff0c;接入网络可以使用有线网口或者wifi路由&#xff0c;有些提示…

「软件设计模式」桥接模式(Bridge Pattern)

深入解析桥接模式&#xff1a;解耦抽象与实现的艺术 一、模式思想&#xff1a;正交维度的优雅解耦 桥接模式&#xff08;Bridge Pattern&#xff09;通过分离抽象&#xff08;Abstraction&#xff09;与实现&#xff08;Implementation&#xff09;&#xff0c;使二者可以独立…

Jenkins 安装插件 二

Jenkins 安装插件 二 一. 打开 Dashboard 打开 Jenkins 界面&#xff0c;不管在任何界面&#xff0c;只需要点击左上角 Dashboard 按钮即可 二. 打开 Manage Jenkins 找到 Manage Jenkins -> System Configuration -> Plugins 点击 Plugins 打开界面如下 Updates&a…

CI/CD(二)docker-compose安装Jenkins

1、docker-compose.yml version: 3.8services:jenkins:image: jenkins/jenkins:lts # 使用官方的 Jenkins LTS 镜像container_name: jenkinsuser: root # 如果需要以 root 用户运行ports:- "8080:8080" # Jenkins Web 界面端口- "50000:50000" # 用于 Jen…

Windows环境安装部署minimind步骤

Windows环境安装部署minimind步骤 必要的软件环境 git git&#xff0c;可下载安装版&#xff0c;本机中下载绿色版&#xff0c;解压到本地目录下&#xff08;如&#xff1a;c:\soft\git.win64&#xff09;&#xff0c;可将此路径添加到PATH环境变量中&#xff0c;供其他程序…

Qt信号槽调用出错:Qt: Dead lock detected while activating a BlockingQueuedConnection

目录 1.现象和原因分析 2. 总结 1.现象和原因分析 就在最近的开发过程中&#xff0c;程序一运行在控制台就打印&#xff1a; Qt: Dead lock detected while activating a BlockingQueuedConnection&#xff1a; 咋一看&#xff0c;怎么出现死锁了呢&#xff1f;仔细看下…

应对DeepSeek总是服务器繁忙的解决方法

最近由于访问量过大&#xff0c;DeepSeek服务器官网经常弹出&#xff1a;“服务器繁忙&#xff0c;请稍后再试”的提示&#xff0c;直接卡成PPT怎么办&#xff1f;服务器繁忙直接看到视觉疲劳&#xff1a; 解决DeepSeek卡顿问题 DeepSeek使用卡顿问题&#xff0c;是因为访问量…

仿叮咚买菜鸿蒙原生APP

# DingdongShopping 这是一个原生鸿蒙版的仿叮咚买菜APP项目 鸿蒙Next发布至今已经有一年多的时间了&#xff0c;但有时候我们想要实现一些复杂的功能或者效果&#xff0c;在开发文档上查阅一些资料还是比较费时的&#xff0c;有可能还找不到我们想要的内容。而社会层面上分享…

HarmonyOS NEXT网络状态监听HTTP和RCP请求网络

当我们在HarmonyOS NEXT中开发的应用&#xff0c;基本上都会使用网络请求&#xff0c;从服务端获取数据在客户端显示或者供用户交互&#xff0c;有时候网络发生变化时&#xff0c;我们需要做一些相应的操作&#xff0c;接下来我们一起来了解下在HarmonyOS NEXT下如何监听网络状…

2025.2.16

Web [GDOUCTF 2023]泄露的伪装&#xff1a; 点进去看就是装神弄鬼&#xff0c;那就直接扫描 果然有东西 第一个是php代码 第二个是个文件 访问发现是一样的 分析一下&#xff1a;使用 file_get_contents($cxk) 函数读取 $cxk 变量中指定的 URL 或文件的内容。 如果读取的内…

python学opencv|读取图像(六十五)使用cv2.boundingRect()函数实现图像轮廓矩形标注

【1】引言 前序学习进程中&#xff0c;已经使用cv2.findContours()函数cv2.drawContours()函数实现图像轮廓识别和标注&#xff0c;这种标注沿着图像的轮廓进行&#xff0c;比较细致。相关文章链接为&#xff1a; python学opencv|读取图像&#xff08;六十四&#xff09;使用…

haproxy实现MySQL服务器负载均衡

1.环境准备 准备好下面四台台服务器&#xff1a; 主机名IP角色open-Euler1192.168.121.150mysql-server1openEuler-2192.168.121.151mysql-server2openEuler-3192.168.121.152clientRocky8-1192.168.121.160haproxy 2.mysql服务器配置 1.下载mariadb #下载mariadb [rootop…

C语言简单练习题

文章目录 练习题一、计算n的阶乘bool类型 二、计算1!2!3!...10!三、计算数组arr中的元素个数二分法查找 四、动态打印字符Sleep()ms延时函数system("cls")清屏函数 五、模拟用户登录strcmp()函数 六、猜数字小游戏产生一个随机数randsrandRAND_MAX时间戳time() 示例 …

C语言之easyX

目录 概要 easyX整体架构 图形绘制 画布宽高 圆形 图片的贴图 加载图像 游戏框架 概要 easyX是一个轻量级的图形库&#xff0c;用于在Windows平台上进行简单的2D图形绘制。它提供了一组简单易用的函数&#xff0c;可以方便地绘制基本的图形元素&#xff0c;如线条、矩形、圆形…

10. Hbase Compaction命令

一. 什么是Compaction 在 HBase 中&#xff0c;频繁进行数据插入、更新和删除操作会生成许多小的 HFile&#xff0c;当 HFile 数量增多时&#xff0c;会影响HBase的读写性能。此外&#xff0c;垃圾数据的存在也会增加存储需求。因此&#xff0c;定期进行 Compact操作&#xff…

告别卡关!XSS挑战之旅全关卡通关思路详解

XSS挑战之旅 XSS测试思路Level1Level2Level3Level4Level5Level6Level7Level8Level9Level10Level11Level12Level13Level14Level15Level16Level17Level18Level19Level20免责声明&#xff1a; XSS测试思路 确定输入输出点&#xff1a; 寻找URL参数、表单输入、HTTP头&#xff08;R…

【Java】分布式锁Redis和Redisson

https://blog.csdn.net/weixin_44606481/article/details/134373900 https://www.bilibili.com/video/BV1nW421R7qJ Redis锁机制一般是由 setnx 命令实现&#xff0c;set if not exists&#xff0c;语法setnx key value&#xff0c;将key设置值为value&#xff0c;如果key不存在…

Python的imutils库详细介绍

imutils 是一个专为简化OpenCV&#xff08;计算机视觉库&#xff09;常见操作而设计的Python工具库&#xff0c;提供了一系列便捷函数&#xff0c;使图像和视频处理更加高效和简洁。以下是对其功能、安装及用法的详细介绍&#xff1a; 1. 安装方法 通过pip安装&#xff1a; p…