C产品如何满足特定用户需求?
- 内容介绍
- 文章标签
- 相关推荐
本文共计934个文字,预计阅读时间需要4分钟。
许多人以为使用 `Directory.CreateDirectory` 创建目标目录,再用 `File.Copy` 逐个复制文件就完成了复制任务。但实际上,这只会复制顶层文件,子目录及其内容则会被丢弃。深层目录复制的核心是遍历+判断+创建+复制四步,且必须严格按照目录优先顺序执行。
常见错误现象:DirectoryNotFoundException 报在子目录路径上,或目标里只有一堆空文件夹,没文件。
- 必须先创建子目录,再拷贝该目录下的文件
- 不能用
Directory.GetFiles(dir, "*", SearchOption.AllDirectories)一次性拉取所有文件路径再处理——它不提供父子层级关系,无法保证创建顺序,遇到长路径或特殊字符时还容易出错 - 推荐用
SearchOption.TopDirectoryOnly配合递归调用,每层只处理当前级的目录和文件
递归方法里必须显式处理目标子目录路径
源路径 "ABC" 要映射到目标路径 "XYZBC",不是简单拼字符串。漏掉路径重映射,会导致所有文件被拷进目标根目录,彻底乱套。
实操建议:
- 递归函数签名建议带两个
string参数:sourceDir和targetDir,每次调用都传入对应层级的完整路径 - 用
Path.Combine(targetDir, subDirName)构造子目录目标路径,别用targetDir + "\" + subDirName——跨平台或 UNC 路径下会挂 - 创建目标子目录前,先调用
Directory.Exists检查,避免重复创建(虽然CreateDirectory本身幂等,但检查能提前暴露权限问题)
File.Copy 的 overwrite 参数不解决所有问题
File.Copy(source, target, true) 确实能覆盖同名文件,但它不会跳过只读文件,也不会处理正在被占用的文件——直接抛 UnauthorizedAccessException 或 IOException。
真实场景中需要更稳健的策略:
- 拷贝前先用
FileAttributes.ReadOnly检查并清除只读属性:File.SetAttributes(target, FileAttributes.Normal) - 对关键文件加 try/catch,记录失败项而不是让整个复制中断
- 不要依赖
File.GetLastWriteTime做增量判断——NTFS 和 FAT32 时间精度不同,网络共享卷还可能有同步延迟;如需增量,应比对File.GetLastWriteTimeUtc+new FileInfo(path).Length
大文件或海量小文件时性能差异明显
纯 .NET Framework 的 File.Copy 在拷大文件(>500MB)时内存占用低、速度稳;但拷成千上万个 1KB 小文件时,频繁的 IO 调度反而比用 FileStream 缓冲读写慢 20%–30%。
可选优化点:
- 小文件场景(平均 FileStream +
BufferedStream,缓冲区设为 64KB 左右 - 禁用临时文件缓存:
FileOptions.NoBuffering对大文件有效,但对小文件有害,慎用 - 避免在循环里反复调用
Path.GetFileName或Path.GetDirectoryName,提前提取好复用
递归深度本身不是瓶颈,.NET 支持上千层没问题;真正卡住的是权限校验、杀毒软件钩子、远程 SMB 延迟这些外部因素——所以日志里一定要记下每个失败路径和 Exception.Message,别只打 “copy failed”。
本文共计934个文字,预计阅读时间需要4分钟。
许多人以为使用 `Directory.CreateDirectory` 创建目标目录,再用 `File.Copy` 逐个复制文件就完成了复制任务。但实际上,这只会复制顶层文件,子目录及其内容则会被丢弃。深层目录复制的核心是遍历+判断+创建+复制四步,且必须严格按照目录优先顺序执行。
常见错误现象:DirectoryNotFoundException 报在子目录路径上,或目标里只有一堆空文件夹,没文件。
- 必须先创建子目录,再拷贝该目录下的文件
- 不能用
Directory.GetFiles(dir, "*", SearchOption.AllDirectories)一次性拉取所有文件路径再处理——它不提供父子层级关系,无法保证创建顺序,遇到长路径或特殊字符时还容易出错 - 推荐用
SearchOption.TopDirectoryOnly配合递归调用,每层只处理当前级的目录和文件
递归方法里必须显式处理目标子目录路径
源路径 "ABC" 要映射到目标路径 "XYZBC",不是简单拼字符串。漏掉路径重映射,会导致所有文件被拷进目标根目录,彻底乱套。
实操建议:
- 递归函数签名建议带两个
string参数:sourceDir和targetDir,每次调用都传入对应层级的完整路径 - 用
Path.Combine(targetDir, subDirName)构造子目录目标路径,别用targetDir + "\" + subDirName——跨平台或 UNC 路径下会挂 - 创建目标子目录前,先调用
Directory.Exists检查,避免重复创建(虽然CreateDirectory本身幂等,但检查能提前暴露权限问题)
File.Copy 的 overwrite 参数不解决所有问题
File.Copy(source, target, true) 确实能覆盖同名文件,但它不会跳过只读文件,也不会处理正在被占用的文件——直接抛 UnauthorizedAccessException 或 IOException。
真实场景中需要更稳健的策略:
- 拷贝前先用
FileAttributes.ReadOnly检查并清除只读属性:File.SetAttributes(target, FileAttributes.Normal) - 对关键文件加 try/catch,记录失败项而不是让整个复制中断
- 不要依赖
File.GetLastWriteTime做增量判断——NTFS 和 FAT32 时间精度不同,网络共享卷还可能有同步延迟;如需增量,应比对File.GetLastWriteTimeUtc+new FileInfo(path).Length
大文件或海量小文件时性能差异明显
纯 .NET Framework 的 File.Copy 在拷大文件(>500MB)时内存占用低、速度稳;但拷成千上万个 1KB 小文件时,频繁的 IO 调度反而比用 FileStream 缓冲读写慢 20%–30%。
可选优化点:
- 小文件场景(平均 FileStream +
BufferedStream,缓冲区设为 64KB 左右 - 禁用临时文件缓存:
FileOptions.NoBuffering对大文件有效,但对小文件有害,慎用 - 避免在循环里反复调用
Path.GetFileName或Path.GetDirectoryName,提前提取好复用
递归深度本身不是瓶颈,.NET 支持上千层没问题;真正卡住的是权限校验、杀毒软件钩子、远程 SMB 延迟这些外部因素——所以日志里一定要记下每个失败路径和 Exception.Message,别只打 “copy failed”。

