博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
本地文件同步——C#源代码
阅读量:6072 次
发布时间:2019-06-20

本文共 2642 字,大约阅读时间需要 8 分钟。

需求描述:

将文件夹A内的文件夹和文件同步到文件夹B。

其实需求也就那么一句话,没啥还需要解释的了吧。详细点说,需要同步文件/文件夹的“新增,删除,重命名,修改”。

一开始我的想法是先Google,然后在博客园找到这篇文章《》。这篇文章的核心来自msdn里面FileSystemWatcher 的解释。就是用对象FileSystemWatcher 去监听文件是否被创建,重命名,删除,修改。如果发生了就调用相对应的事件,将被修改,创建,重命名的文件复制到目标目录B当中。这个例子比较简单,很多事情都没考虑到。而且我认为用FileSystemWatcher 去监听所有的文件,太浪费CPU和内存。

 


我的想法

是采用递归,遍历整个源目录,对比目标目录。

    1. 如果目标目录下没有相对应的文件,将文件复制到目标目录;
    2. 如果文件在两个路径下都存在,但是文件大小和最后写入时间不一致时,将原目录下的文件复制到目标目录下;
    3. 如果文件存在于目标目录下而不存在源目录下,则将目标路径下的文件删除。

实现 

知道如何比较之后就可以进行递归遍历文件夹了。这个是这个软件实现的难点之一,其实也没多难,也就是说这个软件根本就没多难。以下是递归函数:

/// /// 递归核心 同步目录 /// /// 原路径/// 目标路径static void loop(string src, string obj)    // 递归核心 同步目录 {    CopyFistly(src, obj);   //先同步文件    //遍历文件夹,递归调用    DirectoryInfo dirSrc = new DirectoryInfo(src);    DirectoryInfo[] dirs = dirSrc.GetDirectories();    foreach (DirectoryInfo dir in dirs)    {        string str = dir.Name;        if (Directory.Exists(obj + "\\" + dir.Name) == false)        {            str = Directory.CreateDirectory(obj + "\\" + dir.Name).ToString();        }        //注意这里,这里是递归,而且是下面要注意的地方        loop(src + "\\" + dir.ToString(), obj + "\\" + str);        }}

测试了一下结果,在9000+个文件,40+个文件夹下,在我这部破机器上面单纯递归遍历(不复制文件)的时候需要的时间是截枝的十倍以上。简直是只乌龟。。。


优化

所以要想办法缩短时间提高效率。既然复制文件上面我们无法操作,那我们只好在递归上面进行优化。上个星期我发了一篇文章叫做《》。这个时候刚好可以用上这种方法了。因为本身用的就是递归,而且文件夹的结构本身就是一个树的结构,在恰好满足了回溯法的要求。在遍历上面,并不需要在所有的文件夹都遍历一遍。因为有些文件夹并没有发生改变,所有就没有必要遍历下去了。所以就需要在递归调用自己之前先加一个条件,也就是加上约束函数。修改之后,代码如下:

/// /// 递归核心 同步目录 /// /// 原路径/// 目标路径static void loop(string src, string obj)    // 递归核心 同步目录 {    CopyFistly(src, obj);   //先同步文件    //遍历文件夹,递归调用    DirectoryInfo dirSrc = new DirectoryInfo(src);    DirectoryInfo[] dirs = dirSrc.GetDirectories();    foreach (DirectoryInfo dir in dirs)    {        string str = dir.Name;        if (Directory.Exists(obj + "\\" + dir.Name) == false)        {            str = Directory.CreateDirectory(obj + "\\" + dir.Name).ToString();        }        DirectoryInfo dirObj = new DirectoryInfo(str);        //约束函数 在大小不一致的时候进行同步,其他状态不同步        if (GetDirectoryLength(src + "\\" + dir.ToString()) != GetDirectoryLength(obj + "\\" + str))                loop(src + "\\" + dir.ToString(), obj + "\\" + str);    }}

函数GetDirectoryLength(string path)的作用是检查文件夹path的大小。这里只是简单地对比两个文件夹的大小,如果大小一致,则截枝不递归,否则递归。这种方式的效率非常高,因为很多时候并不是都在有文件的复制,所以不需要经常去遍历目录。所以截枝就好了。下面给出GetDirectoryLength(string path)函数的代码。其实该函数也是一个递归,虽然会增加负荷,但是文件多,文件夹深的时候,是很有必要的。

获取文件夹大小

 

 

难点主要在递归和截枝的思想上面。其他方面的解释可以直接查看代码。注释已经很清楚了。下面是整个文件的源代码:

文件同步

 


配置文件的代码

因为要求用配置文件,配置原路径,目的路径等信息,有必要说明一下这个问题。另外需要读配置文件,所以需要引用System.Configuration;命名空间。一下是配置文件app.config代码:


效果:

 

希望本篇文章对你有所用处。

转载地址:http://ujsgx.baihongyu.com/

你可能感兴趣的文章
HDOJ How many ways?? 2157【矩阵高速幂】
查看>>
js 实现首字母大写并且其他全部小写
查看>>
Java判断两个时间段是否有交集
查看>>
linux中tar命令(打包、压缩、解压)、zip和unzip、rar多种压缩文件
查看>>
matlab练习程序(Harris角点检测)
查看>>
【转】QT中QWidget、QDialog及QMainWindow的区别
查看>>
系统运维系列:【第一篇】系统运维课程介绍
查看>>
Cmake编译SDL2
查看>>
使用WiX Toolset创建.NET程序发布Bootstrapper(安装策略管理)(二)——自定义安装...
查看>>
恋愛SLG-「メイド服セット」ゲットチャレンジ!
查看>>
oracle导入导出命令
查看>>
Arduino蓝牙模块实现通信
查看>>
【2019-06-25】失去的原因
查看>>
【转载】sublime text3 全攻略
查看>>
考试认证
查看>>
java学习笔记13-重写与重载
查看>>
Powershell管理系列(二十六)PowerShell操作之批量导出&导入邮箱
查看>>
Linux系统基础网络配置老鸟精华篇
查看>>
【物联网智能网关-13】Html5:Canvas+WebSocket实现远程实时通信(上)
查看>>
为VMware ESXi主机添加本地存储的过程及注意事项-之4
查看>>