有了前六章章的基础,我们来应用一下,写一个文件同步的小程序。

  分析一下,文件同步的功能就是把一个文件夹(源)最新的内容拷贝到另一个文件夹(目的),保持目的文件夹的内容最新。

  开发思路大致为,先找出那些文件是目标文件夹中没有的,那些是更新过得,然后拷贝过去。具体代码如下:

Imports System.IO
Class AppMain
Shared WithEvents sync As New FileSync
Public Shared Sub Main(ByVal args() As String)
Dim source As String = String.Empty, dest As String = String.Empty
Dim result As FileSync.FileSyncResult

If ResolveArgs(args, source, dest) Then
result
= sync.Porcess(source, dest)
ResolveResult(result)
End If

End Sub
''' <summary>
''' 解析输入的参数,成功解析返回true
''' </summary>
''' <param name="args"></param>
''' <param name="source">源文件夹路径</param>
''' <param name="dest">目标文件夹路径</param>
''' <returns>是否解析成功</returns>
''' <remarks>在解析不成功是提示程序的使用方法</remarks>
Private Shared Function ResolveArgs(ByVal args() As String, ByRef source As String, ByRef dest As String) As Boolean
If args.Length <> 2 Then
Call FileSyncHelp()
Return False
End If

source
= args(0)
dest
= args(1)
Return True
End Function
''' <summary>
''' 显示程序帮助信息
''' </summary>
''' <remarks></remarks>
Private Shared Sub FileSyncHelp()
Console.WriteLine(
" -----------------------------------------------------------------------------")
Console.WriteLine(
" 使用示例 FolderSync c:\qq d:\qq")
Console.WriteLine(
" -help 显示帮助信息 ")
Console.WriteLine(
" -----------------------------------------------------------------------------")
End Sub
''' <summary>
''' 文件同步后的结果分析
''' </summary>
''' <param name="result">文件同步结果,FileSyncReslult类型</param>
''' <remarks></remarks>
Private Shared Sub ResolveResult(ByVal result As FileSync.FileSyncResult)
Select Case result
Case FileSync.FileSyncResult.Success
Console.WriteLine(
"同步成功")
Case FileSync.FileSyncResult.SourceFolderNotExist
Console.WriteLine(
"源文件夹不存在")
Case FileSync.FileSyncResult.DestFolderAccessDeny
Console.WriteLine(
"访问目标文件夹出错")
Case FileSync.FileSyncResult.CopyError, FileSync.FileSyncResult.OverrideError
Console.WriteLine(
"写入错误")
Case Else
Console.WriteLine(
"未知的错误")
End Select
End Sub
''' <summary>
''' 处理自定义事件processing
''' </summary>
''' <param name="msg">要显示的消息</param>
''' <remarks></remarks>
Private Shared Sub sync_processing(ByVal msg As String) Handles sync.Processing
Console.WriteLine(msg)
End Sub
End Class
''' <summary>
''' 便于在WinForm中重用而定义的文件同步处理类
''' </summary>
''' <remarks></remarks>
Class FileSync
''' <summary>
''' 可能的同步操作结果
''' </summary>
''' <remarks></remarks>
Public Enum FileSyncResult
Success
SourceFolderNotExist
DestFolderAccessDeny
CopyError
OverrideError
End Enum
''' <summary>
''' 同步中设计到得文件操作类型(复制,覆盖等)
''' </summary>
''' <remarks></remarks>
Private Enum FileSyncOpration
Ignore
Copy
Override
End Enum
''' <summary>
''' 用来存储要同步的文件的具体信息的自定义结构
''' </summary>
''' <remarks></remarks>
Private Structure SyncFile
Dim sourceFileName As String
Dim destFileName As String
Dim operation As FileSyncOpration
End Structure
''' <summary>
''' FileSync的自定义事件
''' </summary>
''' <param name="msg"></param>
''' <remarks></remarks>
Public Event Processing(ByVal msg As String)
''' <summary>
''' 处理文件同步的函数
''' </summary>
''' <param name="source">源文件夹路径</param>
''' <param name="dest">目标文件夹路径</param>
''' <returns>处理结果 FileSyncResult类型</returns>
''' <remarks></remarks>
Public Function Porcess(ByVal source As String, ByVal dest As String) As FileSyncResult

If Not Directory.Exists(source) Then
Return FileSyncResult.SourceFolderNotExist
End If
If Not Directory.Exists(dest) Then
Return FileSyncResult.DestFolderAccessDeny
End If

Return DoSync(source, dest)
End Function
''' <summary>
''' 实际执行文件同步的私有函数
''' </summary>
''' <param name="source">源文件夹路径</param>
''' <param name="dest">目标文件夹路径</param>
''' <returns>处理结果 FileSyncResult类型</returns>
''' <remarks></remarks>
Private Function DoSync(ByVal source As String, ByVal dest As String) As FileSyncResult
Dim syncFiles() As SyncFile = GetSyncFiles(source, dest)
Dim i As Int32 = 0

For i = 0 To UBound(syncFiles)
Dim currentFile As SyncFile = syncFiles(i)
Select Case currentFile.operation
Case FileSyncOpration.Copy
File.Copy(currentFile.sourceFileName, currentFile.destFileName)
RaiseEvent Processing(syncFiles(i).sourceFileName & "...." & "拷贝成功")
Case FileSyncOpration.Override
File.Copy(currentFile.sourceFileName, currentFile.destFileName,
True)
RaiseEvent Processing(syncFiles(i).destFileName & "...." & "更新成功")
End Select
Next

Return FileSyncResult.Success
End Function
''' <summary>
''' 用来装填要同步的文件信息
''' </summary>
''' <param name="source">源文件夹路径</param>
''' <param name="dest">目标文件夹路径</param>
''' <returns>装填好的要同步的文件信息</returns>
''' <remarks></remarks>
Private Function GetSyncFiles(ByVal source As String, ByVal dest As String) As SyncFile()
Dim syncFiles() As SyncFile, i As Int32 = 0
Dim sourceFiles() As String = Directory.GetFiles(source)
Dim destFile As String
Dim action As FileSyncOpration = FileSyncOpration.Ignore

ReDim syncFiles(sourceFiles.Length)

For i = 0 To UBound(sourceFiles)
destFile
= GetDestFileName(sourceFiles(i), dest)

If File.Exists(destFile) = False Then
action
= FileSyncOpration.Copy
ElseIf JundgeLastWriteTime(sourceFiles(i), destFile) Then
action
= FileSyncOpration.Override
End If

syncFiles(i).sourceFileName
= sourceFiles(i)
syncFiles(i).destFileName
= destFile
syncFiles(i).operation
= action
Next

Return syncFiles
End Function
''' <summary>
''' 得到源文件夹中的文件在目标文件夹中的路径
''' </summary>
''' <param name="sourceFileName">源文件夹中的文件路径</param>
''' <param name="destion">目标文件夹</param>
''' <returns>目标文件夹中的路径</returns>
''' <remarks></remarks>
Private Function GetDestFileName(ByVal sourceFileName As String, ByVal destion As String) As String
Return Path.Combine(destion, Path.GetFileName(sourceFileName))
End Function
''' <summary>
''' 判断该文件是否被改写过
''' </summary>
''' <param name="sourceFile">源文件</param>
''' <param name="destFile">目标文件</param>
''' <returns>改写:true,为改写:false</returns>
''' <remarks></remarks>
Private Function JundgeLastWriteTime(ByVal sourceFile As String, ByVal destFile As String) As Boolean
Dim sourceFileInfo As New FileInfo(sourceFile)
Dim destFileInfo As New FileInfo(destFile)

If sourceFileInfo.LastWriteTime.Ticks > destFileInfo.LastWriteTime.Ticks Then
Return True
Else
Return False
End If
End Function
End Class

通过这个练习,把前面学的内容大致都检验了一下,一些还没介绍的内容如Path类,自定义事件,就要自己下处查查资料了。