C#备份文件夹的两种方法
作者:小强~
在C#编程中,文件夹操作是不可或缺的一部分,它允许开发者创建、删除、移动和管理文件系统中的目录结构,本文给大家介绍了C#备份文件夹的两种方法,需要的朋友可以参考下
方法1:通过 递归 或者 迭代 结合 C# 方法
参数说明:
- sourceFolder:源文件夹路径
- destinationFolder:目标路径
- excludeNames:源文件夹中不需备份的文件或文件夹路径哈希表
- errorLog:输出错误log
递归实现:
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; } }
迭代实现:
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有一个漏洞,该方法无法成功捕捉到源文件夹下被占用的文件信息!
到此这篇关于C#备份文件夹的两种方法的文章就介绍到这了,更多相关C#备份文件夹内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!