首页 > 其他分享 >Golang 监控文件夹内文件的增删改(包括子文件夹)

Golang 监控文件夹内文件的增删改(包括子文件夹)

时间:2024-01-11 09:13:14浏览次数:40  
标签:err string nil Golang 文件夹 func 增删 path log

你需要自己处理log部分

package main

import (
    "crypto/md5"
    "fmt"
    "go-admin/log"
    "os"
    "path/filepath"
    "time"

    "github.com/fsnotify/fsnotify"
)

type FileChangeCallback func(absfpname string)

type ConfigFileWatcher struct {
    WatchedDirectory string             // 监控目录
    FileSuffix       string             // 监控的文件类型
    OnFileChange     FileChangeCallback // 相关文件有变更就会调用这个回调
}

func (cfw ConfigFileWatcher) WatchConfigFileChanges() {
    // 注意如果该文件被其他程序占用的话会读取不出内容的。比如vscode打开了文件
    getFileHash := func(filename string) (string, error) {
        data, err := os.ReadFile(filename)
        if err != nil {
            return "", err
        }
        return fmt.Sprintf("%x", md5.Sum(data)), nil
    }

    watcher, err := fsnotify.NewWatcher()
    if err != nil {
        log.Fatal("WatchConfigFileChanges", err.Error(), "")
    }
    defer watcher.Close()

    dir := cfw.WatchedDirectory

    fileInfos := make(map[string]string)

    err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        if info.IsDir() {
            err = watcher.Add(path)
            if err != nil {
                log.Fatal("WatchConfigFileChanges", err.Error(), "")
            }
        } else {
            if filepath.Ext(path) == ".yml" {
                hash, err := getFileHash(path)
                if err != nil {
                    log.Fatal("WatchConfigFileChanges", "获取文件哈希出错:%s", err.Error())
                } else {
                    fileInfos[path] = hash
                }
            }

        }
        return nil
    })
    if err != nil {
        log.Fatal("WatchConfigFileChanges", "%s", err.Error())

    }

    fmt.Println("开始监控...")

    var lastEventTime time.Time
    interval := 500 * time.Millisecond // 设置等待时间为500毫秒

    func() {
        for {
            select {
            case event, ok := <-watcher.Events:
                if !ok {
                    return
                }
                if (event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Create == fsnotify.Create) &&
                    filepath.Ext(event.Name) == cfw.FileSuffix {

                    // 检查时间间隔,如果在等待时间内则跳过
                    if time.Since(lastEventTime) < interval {
                        continue
                    }

                    // 获取文件的最新MD5值
                    newHash, err := getFileHash(event.Name)
                    if err != nil {
                        log.Fatal("WatchConfigFileChanges", "获取文件哈希出错:%s", err.Error())
                    } else {
                        // 对比MD5值,确认文件内容是否发生了变化
                        if prevHash, exists := fileInfos[event.Name]; exists && prevHash == newHash {
                            fmt.Println("文件未更改:", event.Name)
                            log.Log("WatchConfigFileChanges", "文件未更改:%s", event.Name)
                        } else {
                            fileInfos[event.Name] = newHash
                            absPath, _ := filepath.Abs(event.Name)
                            log.Log("WatchConfigFileChanges", "文件修改或创建:%s", absPath)
                            cfw.OnFileChange(absPath)
                        }
                    }

                    // 更新最后事件时间
                    lastEventTime = time.Now()

                    // 因为fsnotify源码常量定义错了。Rename和Remove搞反了
                } else if (event.Op&fsnotify.Rename == fsnotify.Rename) && filepath.Ext(event.Name) == cfw.FileSuffix {
                    // 检查时间间隔,如果在等待时间内则跳过
                    if time.Since(lastEventTime) < interval {
                        continue
                    }
                    absPath, _ := filepath.Abs(event.Name)
                    fmt.Println("文件被删除:", absPath)
                    cfw.OnFileChange(absPath)
                    // 更新最后事件时间
                    lastEventTime = time.Now()
                }
            case err, ok := <-watcher.Errors:
                if !ok {
                    return
                }
                log.Fatal("WatchConfigFileChanges", "错误:%s", err.Error())
            }
        }
    }()

}

 

标签:err,string,nil,Golang,文件夹,func,增删,path,log
From: https://www.cnblogs.com/watermeloncode/p/17957770

相关文章

  • golang 用os.OpenFile写入文件
    funcmain(){ filename:="测试.txt" //如果文件存在,则追加写入,如果文件不存在则新建文件写入 //f,err:=os.OpenFile(filename,os.O_WRONLY|os.O_CREATE|os.O_APPEND,os.ModePerm) //本行是无法写入文件的,因为以O_RDONLY只读方式打开 //f,err:=os.OpenFile(fi......
  • 在excel中打开本地文件或文件夹
    效果演示:A2中输入本地文件或文件夹绝对路径B2中输入公式 =HYPERLINK(A2) 然后回车保存,再次点击B2中的链接会直接打开本地文件夹或文件......
  • Go Gin+MySQL实现增删改查
    一、概述使用Gin框架+MySQL数据库实现增删改查(原生sql)实现步骤:1.导入Gin框架goget-ugithub.com/gin-gonic/gin2.引入MySQL驱动goget-ugithub.com/go-sql-driver/mysql3.注册Gin路由//注册用户路由funcRegisterUser(){......
  • 【golang】GO之认证与授权
    一般公司项目比较多,比较分散,但是对于都是公司的用户来说,用户数据一般是共享的,所以集成统一认证与授权的功能一般就必不可少,这样可以实现一个用户,分配一点权限,能访问公司很多项目.一般的认证与授权方案有OAuth、分布式Session、OpenID和JWT等.目前常用的是OAuth2,其......
  • Windows 下如何查看文件夹被哪个进程所占用
    退出U盘或删除文件时提示文件被占用,可以通过下面的方法处理:1、右击任务栏,启动任务管理器;2、选择“性能“选项卡,点击“资源监视器”;3、点击“CPU”选项卡,在“关联的句柄”右侧的“搜索句柄”输入框输入文件名或文件夹名并点击搜索......
  • Golang如何进行数据库查询
    Golang是一门高效、快速、强大的编程语言,可用于构建各种应用程序,尤其是在Web开发中表现突出。当与数据库结合使用时,Golang提供了一些强大的工具,帮助开发人员操作数据库。在本篇文章中,我们将重点介绍Golang如何进行数据库查询。一、Golang数据库查询Golang中的数据库查询主要有两......
  • 【Windows】Windows OS C盘根目录只能创建文件夹,不能创建文件的问题
    原因:Windows的安全机制解决办法:方法1不要在C盘根目录下创建文件因为这本身不是最佳实践的做法;虽然是废话但是很有道理。方法2修改C盘的安全等级用管理员运行cmd输入icaclsc:\/setintegritylevelM回车后需要正常需要等大约1分钟。如果超时或发生如下报错:复原方法:icaclsc:\/......
  • Golang Defer 必会知识点
    Golang中的一个关键字,用于延迟执行指定的函数调用。在程序执行到defer语句时,该函数调用会被推迟到当前函数返回之前执行,无论当前函数是正常返回还是发生异常退出。Defer语句可以用来在函数执行完毕后清理资源,确保资源的释放不会被遗漏。通过使用defer,我们能够更好地管理和控......
  • Golang 协程配合管道
    请完成goroutine和channel协同工作的案例,具体要求:(1)开启一个writeData协程,向管道mtChan中写入50个整数.(2)开启一个readData协程,从管道intChan中读取writeData写入的数据。(3)注意:writeData和readDate操作的是同一个管道(4)主线程需要等待writeData和readDate协程都完成工作才能退出(如......
  • 前端歌谣-第柒拾叁课-node操作mongodb实现增删改查(图片上传功能)
    前言大家好我是歌谣今天继续给大家带来node操作mongodb实现增删改查实现上传功能环境准备后端mongodb数据库+node前端ejs模板安装处理文件的依赖npmimulter后端启动.\mongod--dbpath.\data\db后台运行连接数据库清空数据前端部分前端目录controller层constUserService=r......