zoukankan      html  css  js  c++  java
  • 定时自动同步文件,支持多文件夹同步,支持过滤文件和文件夹,解决FileSystemWatcher多次文件触发事件(源码)

      博客园里面有很多同步工具和软件,关于FileSystemWatcher类解释的也很多,但收集了很多文章后,感觉没好的方法,自己没事写了一个定时文件同步,借鉴了很多博客园朋友的东西:

    上主菜:

      配置文件:

    <appSettings>
        <!--原地址(多地址;隔开)-->
        <add key="OldAddress" value="F:akup1;F:akup3"/>
        <!--目标地址-->
        <add key="NewAddress" value="F:akup2"/>
        <!--自动同步时间一般晚上23点开始-->
        <add key="syncTime" value="23"/>
        <!--要过滤的文件夹(多文件名;隔开)-->
        <add key="FiltrationFile" value="Error"/>
        <!--要过滤的文件后缀(多后缀;隔开)-->
        <add key="FiltrationSuffix" value="log"/>
      </appSettings>
    

      FileSystemWatcher类的Changed事件在每次文件添加和修改的时候,都会触发多次,不晓得微软为什么会有这样的考虑,我看博客园很多人给的解决方案是记录文件写入时间,同一文件写入文件不得小于500ns;

      

    lock (dict)
                {
                    //过滤文件夹
                    if (FiltrationFile(e.FullPath)) return;
                    //过滤文件后缀
                    if (FiltrationSuffix(e.Name)) return;
                    if (dict.ContainsKey(e.FullPath)) 
                    {
                        if ((new FileInfo(e.FullPath).LastWriteTime - dict[e.FullPath]).TotalMilliseconds <= 500) //同一文件写入时间不得小于500ns
                            return;
                        else
                            dict.Remove(e.FullPath);
                    }
                    if (e.ChangeType == WatcherChangeTypes.Changed)
                    {
                        if (e.ChangeType == WatcherChangeTypes.Deleted)
                        {
                            return;
                        }
                        //判断文件是否存在.
                        if (System.IO.File.Exists(e.FullPath) == true)
                        {
                            dict.Add(e.FullPath, new FileInfo(e.FullPath).LastWriteTime);
                            Task task = new Task(() =>
                            {
                                FileSave(e.Name, e.FullPath);
                            });
                            task.Start();
                        }
                        System.Threading.Thread.Sleep(1000);
                    }
                }

      在同步文件的时候,还有一个问题就是用户文件正在上传,这个触发Change事件都会报错,这个时候需要验证文件是否完整:

      /// <summary>
            /// 判断文件是否完整
            /// </summary>
            /// <param name="path"></param>
            private void Waiting(string path)
            {
                lock (this)
                {
                    while (true)
                    {
                        try
                        {
                            FileStream stream = File.OpenRead(path);
                            stream.Close();
                            stream.Dispose();
                            return;
                        }
                        catch
                        {
    
                            System.Threading.Thread.Sleep(5000);
                        }
                    }
                }
            }

      在一些项目中,一些日志文件或则一些固定的文件夹是不需要同步的,这都需要验证文件路径是否包含不同的文件夹和文件:

    /// <summary>
            /// 过滤文件夹 
            /// </summary>
            private bool FiltrationFile(string fullPath)
            {
                try
                {
                    string file = GetAppConfig("FiltrationFile");
                    if (string.IsNullOrEmpty(file)) return false;
                    file = file.ToLower();
                    if (File.Exists(fullPath) == true)
                    {
                        string[] items = file.Split(';');
                        List<string> list = fullPath.ToLower().Split('\').ToList();
                        list.RemoveAt(list.Count - 1);
                        for (int i = 0; i < items.Length; i++)
                        {
                            if (list.Count(a => a == items[i]) > 0)
                            {
                                return true;
                            }
                        }
                    }
                }
                catch (Exception exp)
                {
                    WriteLog(exp.Message);
                }
                return false;
            }
    
            /// <summary>
            /// 过滤文件名后缀
            /// </summary>
            private bool FiltrationSuffix(string fileName)
            {
                try
                {
                    string file = GetAppConfig("FiltrationSuffix");
                    if (string.IsNullOrEmpty(file)) return false;
                    file = file.ToLower();
                    string suffix = fileName.ToLower().Substring(fileName.LastIndexOf('.') + 1);
                    string[] items = file.Split(';');
                    for (int i = 0; i < items.Length; i++)
                    {
                        if (items[i] == suffix)
                        {
                            return true;
                        }
                    }
                }
                catch (Exception exp)
                {
                    WriteLog(exp.Message);
                }
                return false;
            }

     源码地址:http://files.cnblogs.com/xchit/SyncFile.rar(如果有更好的解决方法可以交流)

  • 相关阅读:
    笨方法学python中执行argv提示ValueError: not enough values to unpack (expected 4, got 1)
    VMware workstation安装
    Redis bigkey分析
    MySQL drop table 影响及过程
    MySQL 大表硬连接删除
    ES elasticsearch 各种查询
    ES elasticsearch 各种聚合
    ES elasticsearch 聚合统计
    ES elasticsearch 实现 count单字段,分组取前多少位,以地理位置中心进行统计
    MySQL行溢出、varchar最多能存多少字符
  • 原文地址:https://www.cnblogs.com/xchit/p/3455801.html
Copyright © 2011-2022 走看看