用C++实现文件夹同步
用C,,实现文件夹同步
?
开发研究与
技术??????本栏目贲任编辑:谢媛媛
用C++实现文件夹同步
林雪云.方德坚’
(福建师范大学福清分校数学和计算机科学系,福建福清350300)
/
摘要:所谓的文件夹同步.也叫实时备份,就是保持目标文件夹中的文件随时和源文件中的文件完全一致.要实现同步,程序就必须
随时知道源文件夹中的文件是否发生了变化.那么该功能是如何实现的呢?本文给出了实现的方法(API函数)和原理,同时用一个C++
Builder中的实例来证明问题.
关键词:文件夹同步;备份;c++Builder;监控;进程;函数
中图分类号:TP311.1文献标识码:A文章编号:1009—3044(2007)05—11302_01
UsingC++ToAchieveFolderSynchronizing
LINXue—yun,FANGDe--jian
(Fu~ngbranchofFujiannormaluniversitymathandcomputersciencedepart
ment,Fuqing350300,China)
Abstract:Foldersynchronizinginotherwordsisreal—timebackupItisaproc
eduretoensurethatthefileswithinthetargetfolderareiden—
ticaltothefileswithintheoriginalfolderatalltimes.Inordertoachievefolders
ynchronizing,itisnecessarytomonitoranychangesmadeto
theoriginalfilesHowistheproceduremadepractical?Thisdocumentwillintr
oducethesolunon(APIfunc6on)anddemonstratethemethod
withseveralreallifeexamplesusingthesoftC++Builder.
KeyWOrdS:Foldersynchronizing;backup;C++Builder;monitor;process;f
unction
1编程思路
对于文件夹同步功能不同的软件采取不同的实现方法.一些
软件采用定时备份的策略来避开这个难题.不管源文件是否已经
变化,只有到了指定的时间间隔.才检查源文件夹和目标文件夹
是否一致,而比较专业的软件则能够在源文件夹发生任何变化时
马上截获这种变化并采取措施使目标文件夹中的文件更新.显
然,后一种方法更可靠.那么,当源文件夹中的文件发生变化时,
程序如何才能马上知道呢?用定时器当然是不可能的.下面.就将
在C++Builder的实现方法介绍如下:
很多人都知道如何实现在一个进程结束前一直等待的方法.
因为Windows是一个多任务系统.所以如果我们在程序中创造一
个进程并执行,那么不论进程是否执行完毕,我们的程序都会马
上返回.典型的例子就是我们在程序中通过WinExc0函数执行一
个Dos程序,即使这个Dos程序还在运行,我们的程序也会继续
执行下面的语句.还可以找到的例子就是批处理文件执行的效
果.如果想要让程序等到外部进程结束才继续运行,就要用Wait
ForSingObject0函数循环监视进程的执行情况,直到发现进程已
经结束再退出循环.继续下面的语句.而监视文件夹是否发生变
化的原理也是采用了这种方法.系统会为我们创造进程,只有当
文件夹发生变化时这个进程才能退出,只有里程退出,我们的程
序才继续运行,并调用同步文件夹的自定义函数TongSu0,然后,
再继续循环监视这个进程……
不同的是,这个进程不是由我们创建并招待的,而是系统创
建并招待的.要创建这个进程.就必须调用API函数FindFirst
ChangeNotification0以及FindNextChangeNotification0.事实上,
当我们调用第一个API函数.系统就会创建一个进程并返回在这
个进程的句柄.这个进程在不停的运行,直到指定的文件夹发生
变化时才退出.而我们就可以通过循环调用WaitForSingleOb.
ieet0函数监视这个进程是否退出(进程退出后这个函数返回),从
而知道文件夹是否已经发生变化.
当文件夹发生变化,这个系统创建的过程就会退出,这时调
用TongBu()函数检查源文件夹已经变化的文件并更新目标文件
夹.然后.当然必须继续监视文件夹的变化,而系统刚刚创建的进
程已经退出,我们必须再次让系统创建这个进程.这时有两个选
择:一个就是再次调用FindFirstChangeNotification()函数.重新
创建进程对指定的文件夹进行监视.另一个就是调用函数Find
NextChangeNotiiication()函数,直接创建进程对上次那个文件夹
进行监视.如果使用第一种方法的话,必须首先关闭上一次创建
进程进行的监视.调用函数FindFirstChangeNotification()即可.
所以从简单性考虑.还是使用第二方法.不过,无论哪种方法,在
不需要监视时都必须调用函数FindCloseChangeNotiiication()关
闭监视.
这样可以在一个循环中不停地创建进程,监视进程,变化后
同步,再次创建进程,监视进程,变化后同步……但是一定要设置
条件可以退出循环,比如一个逻辑变量指示,否则该软件就会”死
路一条”!而且,循环中一定要将系统及当前窗体的消息传出去.
否则,系统除了运行这个软件,什么也干不了啦,可以使用Appli.
cation”--~ProcessMessages()将消息传出去.
2示例程序
下面是一个简单的文件夹同步的示例程序.这个程序在文件
夹同步函数TongBu()中,简单地将源文件夹中所有的文件拷贝
到目标文件夹中覆盖目标文件,并不是很好的解决
,实际上
应该检测源文件夹与目标文件夹不同的文件.只拷贝这些文件即
可,但这是一个示例程序(注:以下程序在C++Builder中调试通
过).
本程序在主窗体Form1中包含两组GroupBox,每组包含一
个DriveCombox和一个DirectoryListBox.分别用来指定源文件
夹和目标文件夹.另外还有两个FileListBox用来显示源文件夹
和目标文件夹中的文件列表.上面这些组件通过相应的属性设置
联系在一起,使改变驱动器时文件夹自动变化,根本不用编写一
行代码.这就是C++Builder让我们着迷的地方,当然具体的设置
方法我就不再赘述了.
至于两个按钮.BitBtnl和BitBtn2的作用是:BitBtn2是用
来退出的,而BitBtnl则是用来开始和停止文件夹变化监控的.如
果正在监控,那么单击一下就停止监控,否则单击一下就开始监
控.我们用一个逻辑变量StartFlag标识目前的监控状态.
各个API函数在源代码中说明其用法.下面的源代码为了节
(下转第1313页)
收稿日期:2007-03-08
作者简介:林雪云(1966-),女,福建福清人,实验师.
1302电臃知识与技术
本栏目责任编辑:谢媛媛.???开发研究与设计技术?
代码,还能支持从代码到模型的逆向变换,将原有的代码转化在
模型.进行再次
,修改和调整以及新一轮的开发,从而为增量
式开发提供支持.这样不仅能够做到分阶段提交产品,也提高了
对用户需求变换的响应速度和应变能力,以满足用户不断变化的
新的需求.因此,一个完善的集成化过程
环境在功能上应满
足以一基本需求:
(1)应能支持开发完备的过程模型(即应能从过程,资源,机
构,行为和信息等5个侧面来描述企事业过程)与系统模型(即应
能从过程,行为,信息和结构等4个侧面来描述一个系统);
(2)在这个环境支持下建立的模型应是一个可执行的过程模
型.即应能支持模型的虚拟执行的实际动作,从而可在不同的层
次上对模型进行分析和优化;
(3)过程模型应采用可视化的图符与正文描述相结合的表达
方式.其可视化模型图的结构应能客观,自然地反映了企事业各
部门间的通信和同步关系;
(4)应能支持建模人员或管理人员按照企事业系统内外部的
约束条件对模型的执行进行灵活的控制,从而实现开发开发过程
与管理过程的交叉:
(5)应能支持从模型自动生成可在Intemet上运行且支持多
平台共享与多数据库存取的应用系统,从而实现对第三代过程工
程自动化的有力支持;
(6)还应能支持对各类组件库的灵活管理,支持基于组件的
程序设计方法,实现过程组件,需求描述,系统结构与软件组件的
复用和组装.
4结语
好的分析与设计可以成就一个好的系统,这就是为什么在软
件开发过程中的需求分析和设计阶段最具挑战性的原因.虽然目
前人们普遍开始采用面向对象的分析与设计,但很少有开发人员
使用形式化的方法.这主要是缺少统一的语言或语义,来为复杂
软件系统的组件进行定义,可视化,构建和编制文档.UML改变了
这一现状.希望大家通过与实际内容的结合,促进UML技术的推
广应用.
参考文献:
【1】邵维忠,杨芙清.面向对象的系统分析[M】.清华大学出版社,
2000(1).
【2】成奋华.现代软件工程[M】.中南大学出版社,2004(6).
【3】丁峰,柳西玲.UML技术应用fM】.高等教育出版社,2004(7).
『4】樊耘,赵波,顾敏.不确定环境下的产品开发柔性研究【J].管
理工程,2000.17(1):34—38.
f5】周秀丽,王旭.新产品开发风险
与决策方法研究[J】.工
业工程与管理,2000.f6):26—28.
f上接第1302页)
省篇幅.省略了自动生成的部分.
BoolStartFlag--fates://是否正在监视//
HANDLEProeHandle=NULL://进程句柄//
TongSu0//文件夹同步函数//
fForm1一FileListBoxl---~Update();//更新列表//
Forrn1一StatusBar1---~SimpleText=“源文件已经改变.正在
更新目标文件夹…”;
Forml---~Update();//删除目标文件夹多余的文件//
forfinti=0;i<Form1---~FileListBox2—hems---~Count;i++)
iff!FileExists(Forml---~DireetoryListBoxl---~Direetory+”\,”+
Forrn1—FileListBox2—Items—Strings[i])1
DeleteFile(Form1---~DireetoryListBox2---~Direetory+
“+F0rrnlFileLiStBox2---qtems---~Strings[i]):
//源文件夹所有文件拷贝到目标文件夹
forfinti=0;i<Forml---~FileListBox1—Items—Count;i++)
fintFH=FileOpenfForml---~DireetoryListBox1
Directory+”\,”+Form1—File”stBox1—Items—
Strings[i],fmOpenRead);
intFL:FileSeek(FH.0.2);
Char*buf=newehadFL+11;
FileSeek(FH.0.o);
FileRead(FH.buLFL):
FileClose(FH);
FH=FileCrerte(Form1---~DirectoryListBox2---~Direetory
+”\,”+Forml---~FileListBox1—Items_Stringsfi1);
FileWrite(FH.buLFL);
FileClose(FH):
Delete[1buf:l
Form1Statusbarl---~SimpleText=“正在监视源文件夹…”:
Forml---~Update0;l
VoidfastcallTForm::BitBtn!Click(T0bjeet*Sender){
BitBtn1--*Caption=“开始”:
Form1---~StatusBarl---~SimpleText=“已经停止同步”;
StartFlag=false;
FindCloseChangNotification(ProcHandle);//关闭监视
GroupBox1-~Enabled=true;
GroupBox2—}Enabled=true;l
else//开始同步
fif(DirectoryListBox1---~Direetory=DireetoryListBox2
-
~Directory){
MessageBox(Handle,”源文件夹和目标文件夹不能相同”错
误”,MBOK);
return;}
BitBtn1--~Caption=“停止”:
StartFlag=tree;
Form1----~StartBarl---~SimpleText=“正在监视源文件夹…”;
//同步时不能修改源文件夹及目标文件夹
GroupBox1---~Enabled=false;
GroupBox2---~Enabled=false;
ProcHandle=FindFirstChangeNotification(DirectoryListBoxl
---
~Direetory.e—str(),ture,
FILE-NOTIFY—CHANGE—FILEAME
FILENOTIFYCHANGEDIRNAME
FILE—
NOTIFY—CHANGE—SIZE);//创建监视,第一个参数是
要监视的文件夹:第二个参数为Ture它同时监视其下一级文件
夹.否则不监视:第三个参数是要监视的哪些变化?
DW0RDre=l:
While(re)//等待源文件夹改变,如果re=0则进程结束
{if(!StartFlag)retum;//手动停止
re=WaitForSingleObjeet(ProcHandle,10o);
Application--~ProcessMessages();l
TongBU();.
Again;
re=l;
FindNextChangeNotifieation(ProeHandle);11继续监视’
While(re)//等待源文件夹改变
fif(!StarFlag)retum;
re=WaitForSingleObjeet(ProeHandle,10o);
Application---~ProcessMessages();}
TongSu0;
gotoagain;}}
VoidfastcallTForrn1::BitB协2Click(TObject*Sender)
{close;//关闭}
参考文献:
【1】谢敏.应用C++Builder实现实时数据采集,显示的方法[JJ.
电子工程师.(32.1).
[2】茜西.文件夹同步好帮手JFileSyn[J].计算机文摘.2005,(8).
[3】朱时银.C++Builder5.0编程实例与技I5[M].北京:机械工业
出版社.2001.
[4]张晓东.C++Builder5程序设计[M】.北京:中国铁道出版社,
2OO2.
[5】(美)KenGetzMikeGilbert.VBA高级开发指南[M】.北京:电
子工业出版社.1997.
『61刘森林.一种基于C++Builder的过程控制系统设计与实现
[J1.东南大学,2003,9(33):158-161.
1313