• 定时自动同步文件,支持多文件夹同步,支持过滤文件和文件夹,解决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(如果有更好的解决方法可以交流)

  • 相关阅读:
    Unity3D读取assetbundle
    Unity3D 发布成exe之后黑屏
    Unity3D优化总结
    Unity3D中中 rect[2] == rt->GetGLWidth() && rect[3] == rt->GetGLHeight()错误的原因及解决方法
    C# mysql 插入数据,中文乱码的解决方法
    WPF Canvas做自动缩放时获取控件的实际高度
    面向对象
    常用模块介绍
    python异常处理,多线程,多进程
    python生成器,递归调用
  • 原文地址:https://www.cnblogs.com/xchit/p/3455801.html
Copyright © 2020-2023  润新知