C#備份文件夾的兩種方法
方法1:通過 遞歸 或者 迭代 結(jié)合 C# 方法
參數(shù)說明:
- sourceFolder:源文件夾路徑
- destinationFolder:目標(biāo)路徑
- excludeNames:源文件夾中不需備份的文件或文件夾路徑哈希表
- errorLog:輸出錯(cuò)誤log
遞歸實(shí)現(xiàn):
private bool CopyAllFolder(string sourceFolder, string destinationFolder, HashSet<string> excludeNames, out string errorLog)
{
errorLog = string.Empty;
try
{
if (!Directory.Exists(destinationFolder))
{
Directory.CreateDirectory(destinationFolder);
}
string[] directories = Directory.GetDirectories(sourceFolder);
string[] files = Directory.GetFiles(sourceFolder);
foreach (string file in files)
{
if (excludeNames.Count != 0 && excludeNames.Contains(file))
{
continue;
}
try
{
if (!BRTools.IsFileReady(file) || !BRTools.IsNotFileInUse(file, out errorLog)) // 檢測(cè)文件是否被占用
{
return false;
}
string destinationFile = Path.Combine(destinationFolder, Path.GetFileName(file));
File.Copy(file, destinationFile, true);
}
catch (Exception ex)
{
errorLog += $"Error copying file '{file}': {ex.Message}\n";
return false;
}
}
foreach (string directory in directories)
{
if (excludeNames.Count != 0 && excludeNames.Contains(directory))
{
continue;
}
string destinationSubFolder = Path.Combine(destinationFolder, Path.GetFileName(directory));
if (!CopyAllFolder(directory, destinationSubFolder, excludeNames, out string subfolderErrorLog))
{
errorLog += subfolderErrorLog;
return false;
}
}
return true;
}
catch (Exception ex)
{
errorLog = $"Error during folder copy: Message = '{ex.Message}', StackTrace = '{ex.StackTrace}'\n";
return false;
}
}
迭代實(shí)現(xiàn):
private bool CopyAllFolder(string sourceFolder, string destinationFolder, HashSet<string> excludeNames, out string errorLog)
{
errorLog = string.Empty;
try
{
if (!Directory.Exists(destinationFolder))
{
Directory.CreateDirectory(destinationFolder);
}
Stack<string> directoryStack = new Stack<string>();
directoryStack.Push(sourceFolder);
while (directoryStack.Count > 0)
{
string currentDirectory = directoryStack.Pop();
string[] directories = Directory.GetDirectories(currentDirectory);
string[] files = Directory.GetFiles(currentDirectory);
foreach (string file in files)
{
if (excludeNames.Count != 0 && excludeNames.Contains(file))
{
continue;
}
try
{
if (!BRTools.IsFileReady(file) || !BRTools.IsNotFileInUse(file, out errorLog))
{
return false;
}
string destinationFile = Path.Combine(destinationFolder, Path.GetFileName(file));
File.Copy(file, destinationFile, true);
}
catch (Exception ex)
{
errorLog += $"Error copying file '{file}': {ex.Message}\n";
return false;
}
}
foreach (string directory in directories)
{
if (excludeNames.Count != 0 && excludeNames.Contains(directory))
{
continue;
}
string destinationSubFolder = Path.Combine(destinationFolder, Path.GetFileName(directory));
if (!CopyAllFolder(directory, destinationSubFolder, excludeNames, out string subfolderErrorLog))
{
errorLog += subfolderErrorLog;
return false;
}
directoryStack.Push(directory);
}
}
return true;
}
catch (Exception ex)
{
errorLog = $"Error during folder copy: Message = '{ex.Message}', StackTrace = '{ex.StackTrace}'\n";
return false;
}
}
方法2:利用 Windows API
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
public static extern int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SHFILEOPSTRUCT
{
public IntPtr hwnd;
public int wFunc;
public string pFrom;
public string pTo;
public short fFlags;
public bool fAnyOperationsAborted;
public IntPtr hNameMappings;
}
const int FO_COPY = 0x0002;
const int FOF_NOCONFIRMATION = 0x0010;
const int FOF_SILENT = 0x0004;
const int FOF_NO_UI = FOF_NOCONFIRMATION | FOF_SILENT;
private bool CopyDirectory(string sourceDir, string destDir, out string errorLog)
{
errorLog = string.Empty;
try
{
SHFILEOPSTRUCT fileOp = new SHFILEOPSTRUCT();
fileOp.wFunc = FO_COPY;
fileOp.pFrom = sourceDir + '\0' + '\0'; // Must end with double null character
fileOp.pTo = destDir + '\0' + '\0'; // Must end with double null character
//fileOp.fFlags = FOF_NO_UI;
fileOp.fFlags = FOF_NO_UI | FOF_NOCONFIRMATION; // 忽略UI和確認(rèn)對(duì)話框
int result = SHFileOperation(ref fileOp);
// 檢查返回值
if (result != 0)
{
errorLog = $"SHFileOperation failed with error code: {result}";
return false;
}
return true;
}
catch (Exception ex)
{
errorLog = $"Failed to copy the entire folder '{sourceDir}': Message = '{ex.Message}', StackTrace = '{ex.StackTrace}'\n";
return false;
}
}
private bool CopyFolder(string sourceFolder, string destinationFolder, HashSet<string> excludeNames, out string errorLog)
{
errorLog = string.Empty;
try
{
if (!CopyDirectory(sourceFolder, destinationFolder, out errorLog))
{
this.logger.Warning($"errorLog: {errorLog}");
return false;
}
if (excludeNames.Count != 0)
{
foreach (var item in excludeNames)
{
var targetPath = Path.Combine(destinationFolder, GetSonFolderPath(sourceFolder, item)); // 獲取已備份路徑下需排除的文件夾或文件路徑
if (Directory.Exists(item))
{
DeleteDir(targetPath);
}
if(File.Exists(item))
{
DeleteDir(targetPath);
}
}
}
return true;
}
catch(Exception ex)
{
errorLog = $"Error during folder copy, and exception is: Message = '{ex.Message}', StackTrace = '{ex.StackTrace}'\n";
return false;
}
}
private string GetSonFolderPath(string folderPath, string targetPath)
{
string result = string.Empty;
try
{
folderPath = folderPath.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
if (!isFilePath(targetPath))
{
targetPath = targetPath.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
}
else
{
targetPath = Path.GetDirectoryName(targetPath).TrimEnd(Path.DirectorySeparatorChar);
}
if (targetPath.StartsWith(folderPath, StringComparison.OrdinalIgnoreCase))
{
result = targetPath.Substring(folderPath.Length);
}
}
catch (Exception)
{
result = string.Empty;
}
return result;
}
private bool isFilePath(string targetPath)
{
if (Path.HasExtension(targetPath) && File.Exists(targetPath))
return true;
return false;
}
private void DeleteFile(string file)
{
if (File.Exists(file))
{
FileInfo fi = new FileInfo(file);
if (fi.IsReadOnly)
{
fi.IsReadOnly = false;
}
File.Delete(file);
}
}
private void DeleteDir(string dir)
{
if (Directory.Exists(dir))
{
foreach (string childName in Directory.GetFileSystemEntries(dir))
{
if (File.Exists(childName))
{
FileInfo fi = new FileInfo(childName);
if (fi.IsReadOnly)
{
fi.IsReadOnly = false;
}
File.Delete(childName);
}
else
DeleteDir(childName);
}
Directory.Delete(dir, true);
}
}
注意:方法2有一個(gè)漏洞,該方法無法成功捕捉到源文件夾下被占用的文件信息!
到此這篇關(guān)于C#備份文件夾的兩種方法的文章就介紹到這了,更多相關(guān)C#備份文件夾內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Unity UGUI的HorizontalLayoutGroup水平布局組件介紹使用
這篇文章主要為大家介紹了Unity UGUI的HorizontalLayoutGroup水平布局組件介紹使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
C#使用開源驅(qū)動(dòng)連接操作MySQL數(shù)據(jù)庫
這篇文章主要介紹了C#使用開源驅(qū)動(dòng)連接操作MySQL數(shù)據(jù)庫,本文講解使用SourceForge上的mysqldrivercs驅(qū)動(dòng)連接操作MySQL數(shù)據(jù)庫,需要的朋友可以參考下2015-02-02
基于C#實(shí)現(xiàn)簡(jiǎn)單的音樂播放器
這篇文章主要介紹了如何基于C#實(shí)現(xiàn)簡(jiǎn)單的音樂播放器,考慮到需求中的界面友好和跨版本兼容性,我們可以選擇選擇Windows Forms作為開發(fā)平臺(tái),Windows Forms提供了一個(gè)簡(jiǎn)單而強(qiáng)大的方法來創(chuàng)建桌面應(yīng)用程序,文中通過代碼示例給大家講解的非常詳細(xì),需要的朋友可以參考下2024-05-05
C#中使用@聲明變量示例(逐字標(biāo)識(shí)符)
這篇文章主要介紹了C#中使用@聲明變量示例(逐字標(biāo)識(shí)符)在C#中,@符號(hào)不僅可以加在字符串常量之前,使字符串不作轉(zhuǎn)義之用,還可以加在變量名之前,使變量名與關(guān)鍵字不沖突,這種用法稱為“逐字標(biāo)識(shí)符”,需要的朋友可以參考下2015-06-06
淺析C#數(shù)據(jù)類型轉(zhuǎn)換的幾種形式
本篇文章是對(duì)C#中數(shù)據(jù)類型轉(zhuǎn)換的幾種形式進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-07-07
C#實(shí)現(xiàn)批量重命名文件的項(xiàng)目實(shí)踐
文件重命名是一個(gè)在IT行業(yè)中常見的任務(wù),它涉及到對(duì)大量文件進(jìn)行系統(tǒng)性的命名更改,以便于更有效的文件管理和數(shù)據(jù)檢索,下面就來詳細(xì)的介紹一下C#實(shí)現(xiàn)批量重命名文件,感興趣的可以了解一下2026-05-05

