大家是不是平常都有好多檔案需要定期備份?如歌曲、視頻、檔案,代碼檔案等等,如果經常增加洗掉修改檔案,就需要定期備份,最早之前檔案都不大的時候我都是手工先全部洗掉,然后再全部拷貝,感覺比較保險,后來有了很大的電影檔案和很瑣碎的代碼檔案之后,這樣搞太折磨人,就學網上說的用Xcpoy組裝了一個批處理,學了C#后,感徑訓是做一個GUI體驗更好用起來更方便,至于專業的工具,還真沒怎么試過,有點不放心吧,有好用的倒是可以試試,現在先自己做一個用著吧,

關鍵代碼如下:
private async void btnBackUp_Click(object sender, EventArgs e) { string sourceDirectory = txtSource.Text; string targetDirectory = txtTarget.Text; if (sourceDirectory.ToLower() == targetDirectory.ToLower()) { Console.WriteLine("源目錄和備份目錄不能是同一目錄!"); MessageBox.Show("源目錄和備份目錄不能是同一目錄!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } DirectoryInfo diSource = new DirectoryInfo(sourceDirectory); // 源目錄 DirectoryInfo diTarget = new DirectoryInfo(targetDirectory); // 備份目錄 if (diTarget.Name != diSource.Name) diTarget = new DirectoryInfo(Path.Combine(diTarget.FullName, diSource.Name)); // 創建同名目錄 if (!diTarget.Exists) diTarget.Create(); // 如果該目錄已存在,則此方法不執行任何操作 btnBackUp.Enabled = false; txtSource.Enabled = false; txtTarget.Enabled = false; lblWork.Text = "備份開始!"; if (await CopyAllAsync(diSource, diTarget)) { lblWork.Text = "備份完成!"; MessageBox.Show("備份完畢!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } else lblWork.Text = "出現錯誤!"; btnBackUp.Enabled = true; txtSource.Enabled = true; txtTarget.Enabled = true; btnBackUp.Focus(); } public async Task<bool> CopyAllAsync(DirectoryInfo source, DirectoryInfo target) { try { foreach (FileInfo fi in source.GetFiles()) // 復制最新檔案 { Console.WriteLine(@"準備復制檔案 {0}\{1}", target.FullName, fi.Name); // Name不含路徑,僅檔案名 FileInfo newfi = new FileInfo(Path.Combine(target.FullName, fi.Name)); if (!newfi.Exists || (newfi.Exists && fi.LastWriteTime > newfi.LastWriteTime)) { Console.WriteLine("正在復制檔案 {0}", newfi.FullName); lblWork.Text = string.Format("正在復制檔案 {0}", newfi.FullName); if (newfi.Exists && newfi.IsReadOnly) newfi.IsReadOnly = false; // 覆寫或洗掉只讀檔案會產生例外:對路徑“XXX”的訪問被拒絕 fi.CopyTo(newfi.FullName, true); // Copy each file into it's new directory } } foreach (FileInfo fi2 in target.GetFiles()) // 洗掉源目錄沒有而目標目錄中有的檔案 { FileInfo newfi2 = new FileInfo(Path.Combine(source.FullName, fi2.Name)); if (!newfi2.Exists) { Console.WriteLine("正在洗掉檔案 {0}", fi2.FullName); lblWork.Text = string.Format("正在洗掉檔案 {0}", fi2.FullName); if (fi2.IsReadOnly) fi2.IsReadOnly = false; fi2.Delete(); // 沒有權限(如系統盤需管理員權限)會產生例外,檔案不存在不會產生例外 } } foreach (DirectoryInfo di in source.GetDirectories()) // 復制目錄(實際上是創建同名目錄,和源目錄的屬性不同步) { Console.WriteLine(" {0} {1}", di.FullName, di.Name); // Name不含路徑,僅本級目錄名 Console.WriteLine(@"準備創建目錄 {0}\{1}", target.FullName, di.Name); DirectoryInfo newdi = new DirectoryInfo(Path.Combine(target.FullName, di.Name)); if (!newdi.Exists) // 如果CopyAllAsync放在if里的bug: 只要存在同名目錄,則不會進行子目錄和子檔案的檢查和更新 { Console.WriteLine("正在創建目錄 {0}", newdi.FullName); lblWork.Text = string.Format("正在復制目錄 {0}", newdi.FullName); DirectoryInfo diTargetSubDir = target.CreateSubdirectory(di.Name); // 創建目錄 Console.WriteLine("完成創建目錄 {0}", diTargetSubDir.FullName); } if (await CopyAllAsync(di, newdi) == false) return false; ; // Copy each subdirectory using recursion } foreach (DirectoryInfo di2 in target.GetDirectories()) // 洗掉源目錄沒有而目標目錄中有的目錄(及其子目錄和檔案) { DirectoryInfo newdi2 = new DirectoryInfo(Path.Combine(source.FullName, di2.Name)); if (!newdi2.Exists) { Console.WriteLine("正在洗掉目錄 {0}", di2.FullName); lblWork.Text = string.Format("正在洗掉目錄 {0}", di2.FullName); di2.Delete(true); // 只讀的目錄和檔案也能洗掉,如不使用引數則例外"目錄不是空的" } } return true; } catch (Exception e) { Console.WriteLine(e.Message); MessageBox.Show(e.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } }
注意事項:
// 檔案和目錄的創建日期為首次全新復制時的創建時間
// 檔案復制后修改日期始終保持原先的不變,目錄的修改日期為首次全新復制時的創建時間(因為本就是新建)
// 單純的覆寫不會改變修改時間和創建時間
// 檔案發生的屬性變化全新復制時可以保留(無法通過更新時間判斷檔案的屬性變化)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/189209.html
標籤:.NET技术
上一篇:用C#寫差異檔案備份工具
