C#備份文件夾的兩種方法
更新時間:2024年12月15日 08:28:39 作者:小強~
在C#編程中,文件夾操作是不可或缺的一部分,它允許開發(fā)者創(chuàng)建、刪除、移動和管理文件系統(tǒng)中的目錄結(jié)構(gòu),本文給大家介紹了C#備份文件夾的兩種方法,需要的朋友可以參考下
方法1:通過 遞歸 或者 迭代 結(jié)合 C# 方法
參數(shù)說明:
- sourceFolder:源文件夾路徑
- destinationFolder:目標路徑
- excludeNames:源文件夾中不需備份的文件或文件夾路徑哈希表
- errorLog:輸出錯誤log
遞歸實現(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)) // 檢測文件是否被占用
{
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;
}
}
迭代實現(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和確認對話框
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有一個漏洞,該方法無法成功捕捉到源文件夾下被占用的文件信息!
到此這篇關(guān)于C#備份文件夾的兩種方法的文章就介紹到這了,更多相關(guān)C#備份文件夾內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Quartz.Net任務和觸發(fā)器實現(xiàn)方法詳解
這篇文章主要介紹了Quartz.Net任務和觸發(fā)器實現(xiàn)方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-12-12
C#?Winform消息通知系統(tǒng)托盤氣泡提示框ToolTip控件
這篇文章主要為大家介紹了C#或Winform中的消息通知之系統(tǒng)托盤的氣泡提示框窗口(系統(tǒng)toast通知)、ToolTip控件和ToolTipText屬性詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08

