C#备份文件夹的两种方法

 更新时间:2024年12月15日 08:28:39   作者:小强~  
在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#备份文件夹内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C# Color.FromArgb()及系统颜色对照表一览

    C# Color.FromArgb()及系统颜色对照表一览

    这篇文章主要介绍了C# Color.FromArgb()及系统颜色对照表一览,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • C#使用RabbitMQ的详细教程

    C#使用RabbitMQ的详细教程

    RabbitMQ 是一个功能强大的消息队列系统,可用于在分布式系统中进行可靠的消息传递,本篇博客将详细介绍如何在 C# 中使用 RabbitMQ 实现各种消息队列操作,并通过代码介绍的非常详细,需要的朋友可以参考下
    2024-08-08
  • Unity后处理效果之边角压暗

    Unity后处理效果之边角压暗

    这篇文章主要为大家详细介绍了Unity后处理效果之边角压暗,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • C#读写Config配置文件案例

    C#读写Config配置文件案例

    这篇文章介绍了C#读写Config配置文件的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • Unity3D应用之时钟与钟表小组件的使用教程

    Unity3D应用之时钟与钟表小组件的使用教程

    这篇文章主要来和大家详细介绍一下Unity3D应用开发中的时钟和钟表小组件的使用,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-01-01
  • 深入解析C#编程中struct所定义的结构

    深入解析C#编程中struct所定义的结构

    这篇文章主要介绍了C#编程中struct所定义的结构,与C++一样,C#语言同时拥有类和结构,需要的朋友可以参考下
    2016-01-01
  • 详解C#中有趣的 SourceGenerator生成器

    详解C#中有趣的 SourceGenerator生成器

    源生成器是Roslyn编译器的一个强大特性,允许开发者在编译阶段注入自定义代码,本文通过一个实例探究源生成器的使用方法及其在AOT场景的应用,并利用WinDbg工具深入分析Roslyn的内部机制
    2024-10-10
  • C#多线程开发实战记录之线程基础

    C#多线程开发实战记录之线程基础

    线程是一个独立的运行单元,每个进程内部有多个线程,每个线程可以各自同时执行指令,每个线程有自己独立的栈,但是与进程内的其他线程共享内存,这篇文章主要给大家介绍了关于C#多线程开发实战记录之线程基础的相关资料,需要的朋友可以参考下
    2021-09-09
  • C# TreeView无限目录树实现方法

    C# TreeView无限目录树实现方法

    这篇文章主要介绍了C# TreeView无限目录树实现方法,实例分析了TreeView节点操作的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2016-06-06
  • C# 全角和半角转换以及判断的简单代码

    C# 全角和半角转换以及判断的简单代码

    这篇文章介绍了在C#中判断和转换全角半角的方法,有需要的朋友可以参考一下
    2013-07-07

最新评论