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#备份文件夹内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Quartz.Net任务和触发器实现方法详解

    Quartz.Net任务和触发器实现方法详解

    这篇文章主要介绍了Quartz.Net任务和触发器实现方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-12-12
  • Unity多语言转换工具的实现

    Unity多语言转换工具的实现

    这篇文章主要为大家详细介绍了Unity多语言转换工具的实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06
  • C#微信公众号开发 微信事件交互

    C#微信公众号开发 微信事件交互

    这篇文章主要介绍了C#微信公众号开发,微信事件交互的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • C# Winform消息通知系统托盘气泡提示框ToolTip控件

    C# Winform消息通知系统托盘气泡提示框ToolTip控件

    这篇文章主要为大家介绍了C#或Winform中的消息通知之系统托盘的气泡提示框窗口(系统toast通知)、ToolTip控件和ToolTipText属性详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • C#利用雪花算法实现生成ID工具类

    C#利用雪花算法实现生成ID工具类

    雪花算法表示生成的ID如雪花般独一无二,该算法源自Twitter,主要用于解决分布式系统的唯一Id生成问题,本文主要介绍了C#如何利用利用雪花算法实现生成ID,需要的可以参考下
    2023-12-12
  • C#中lock用法详解

    C#中lock用法详解

    这篇文章主要介绍了C#中lock用法,以实例形式详细分析了lock语句的用法及用途,需要的朋友可以参考下
    2014-11-11
  • C#中abstract的用法详解

    C#中abstract的用法详解

    abstract可以用来修饰类,方法,属性,索引器和时间,这里不包括字段. 使用abstrac修饰的类,该类只能作为其他类的基类,不能实例化,而且abstract修饰的成员在派生类中必须全部实现,不允许部分实现,否则编译异常
    2016-12-12
  • C#启动windows服务方法的相关问题分析

    C#启动windows服务方法的相关问题分析

    C#启动windows服务的方法都是什么呢?C#启动服务类型为Disabled的windows服务会遇到什么样的问题呢?那么本文就向你介绍C#启动windows服务的方法的相关内容
    2012-12-12
  • 关于C#程序优化的五十种方法

    关于C#程序优化的五十种方法

    这篇文章主要介绍了C#程序优化的五十个需要注意的地方,使用c#开发的朋友可以看下
    2013-09-09
  • .NET 某云采购平台API 挂死问题解析

    .NET 某云采购平台API 挂死问题解析

    这篇文章主要介绍了.NET 某云采购平台API 挂死问题解析,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-11-11

最新评论