zoukankan      html  css  js  c++  java
  • 使用FileSystemWatcher监视文件更改

        FileSystemWatcher相关介绍请看MSDN(http://msdn.microsoft.com/zh-cn/library/system.io.filesystemwatcher.aspx),本文只是对Changed事件多次触发做一点处理(纯粹个人见解)。

        MSDN对Changed事件的定义为:当对所监视的目录中的文件或目录的大小、系统特性、上次写入时间、上次访问时间或安全权限进行更改时,将引发 Changed 事件。

        首先定义一个基础类型:

        public class FileWatcher
        {
            FileSystemWatcher fsw;
            public event Action<FileSystemEventArgs> OnChange;
    
            public FileWatcher(string path, string filter)
            {
                fsw = new FileSystemWatcher();
                fsw.Path = path;
                fsw.Filter = filter;
                fsw.NotifyFilter = NotifyFilters.LastWrite;
                fsw.Changed += fsw_Changed;
                fsw.EnableRaisingEvents = true;
            }
    
            void fsw_Changed(object sender, FileSystemEventArgs e)
            {
                if (CanRaiseChange(e))
                    RaiseChange(e);
            }
    
            protected virtual bool CanRaiseChange(FileSystemEventArgs e)
            {
                return true;
            }
    
            protected virtual void RaiseChange(FileSystemEventArgs e)
            {
                if (OnChange != null)
                    OnChange.BeginInvoke(e, null, null);//考虑到OnChange执行时间有可能比较长
            }
        }

        因为只需要监视文件内容更改,仅仅监视文件最后写入时间已经足够。在本文之前,找了很多网站,均是以System.Threading.Timer来解决多次触发问题,但由于无法对Timer.Change方法传递额外的参数,在准确性上未免打一些折扣,而且某些解决方案无法处理同一时间修改的多个文件,遂决定自己实现。

        具体思路为:
        1、首先创建一个字典,以文件的完整路径为Key,最后触发Changed时间为Value
        2、对于每个触发的Changed事件,首先判断被修改文件的完整路径是否在字典中,如果不存在则向字典添加
        3、如果存在于字典中,则判断当前被修改文件上一次Changed事件触发的时间与当前触发时间间隔,这里暂且设置为500毫秒
        4、对于500毫秒以内的不作处理
        5、对于超出500毫秒的进行处理,并更新当前被修改文件的Changed事件触发时间

        代码如下:

        public class MyFileWatcher : FileWatcher
        {
            private Dictionary<string, DateTime> changesHistory = new Dictionary<string, DateTime>();
    
            public MyFileWatcher(string path, string filter) :
                base(path, filter) { }
    
            protected override bool CanRaiseChange(FileSystemEventArgs e)
            {
                if (!changesHistory.ContainsKey(e.FullPath))
                {
                    Console.WriteLine("a");
                    changesHistory.Add(e.FullPath, DateTime.Now);
                    return true;
                }
                
                DateTime now = DateTime.Now;
                bool canRaise = (now - changesHistory[e.FullPath]).TotalMilliseconds >= 500;
                if (canRaise)
                    changesHistory[e.FullPath] = now;
                Console.WriteLine(canRaise);
                return canRaise;
            }
        }

        测试代码:

        public static void Main(string[] args)
        {
            MyFileWatcher mfw = new MyFileWatcher("g:\\test\\", "*.txt");
            mfw.OnChange += new Action<FileSystemEventArgs>(fw_OnChange);
            Console.Read();
        }
        
        static void fw_OnChange(FileSystemEventArgs obj)
        {
            Console.WriteLine("{0} {1}", DateTime.Now, obj.FullPath);
        }

        本方法存在一个问题,就是需要监视的文件增多以后,changesHistory字典会不断增大,对性能会有一定影响。可以考虑在CanRaiseChange方法里删除一部分时间间隔比较长的元素。

        另外,对于多线程同时修改一个文件的情况,本方法也无法解决,但已经能满足我的需求。

  • 相关阅读:
    poj 3528 (三维几何求凸包+凸包表面积)
    dijkstra模板(好像是斐波那契额堆优化,但我为什么看起来像优先队列优化,和spfa一样)
    最大空凸包模板
    ICPC 2017–2018, NEERC, Northern Subregional Contest St Petersburg, November 4, 2017 I题
    hdu 5248 序列变换
    hdu 2063(二分图模板测试)
    组合数
    85. Maximal Rectangle 由1拼出的最大矩形
    750. Number Of Corner Rectangles四周是点的矩形个数
    801. Minimum Swaps To Make Sequences Increasing 为使两个数组严格递增,所需要的最小交换次数
  • 原文地址:https://www.cnblogs.com/lwme/p/1831936.html
Copyright © 2011-2022 走看看