C++递归文件复制中引入多线程加速的实现方法求助
多线程优化递归文件复制的C++实现
优化思路
- 目录结构保持串行创建:子目录依赖父目录存在,必须先完成父目录创建才能处理子目录内容
- 文件、软链接、硬链接的复制并行执行:这类IO密集型任务适合用多线程提升效率
- 修复硬链接处理逻辑:原代码仅打印硬链接,改为直接创建硬链接而非复制文件,既保留属性又提升效率
- 用
std::vector<std::thread>管理线程,确保所有任务完成后再返回
完整优化代码
#include <fstream> #include <filesystem> #include <iostream> #include <thread> #include <vector> #include <stdexcept> namespace fs = std::filesystem; // 复制文件(优化错误处理与大文件分块复制) void cpFile(const fs::path& srcPath, const fs::path& dstPath) { try { std::ifstream srcFile(srcPath, std::ios::binary | std::ios::ate); if (!srcFile) { throw std::runtime_error("无法打开源文件: " + srcPath.string()); } std::ofstream dstFile(dstPath, std::ios::binary); if (!dstFile) { throw std::runtime_error("无法创建目标文件: " + dstPath.string()); } // 1MB缓冲区分块复制,避免大文件占用过多内存 const std::streamsize bufferSize = 1024 * 1024; std::vector<char> buffer(bufferSize); srcFile.seekg(0); while (srcFile.read(buffer.data(), bufferSize)) { dstFile.write(buffer.data(), srcFile.gcount()); } dstFile.write(buffer.data(), srcFile.gcount()); srcFile.close(); dstFile.close(); } catch (const std::exception& e) { std::cerr << "文件复制失败: " << e.what() << std::endl; } } // 复制软链接 void cpSoftLink(const fs::path& srcPath, const fs::path& dstPath) { try { if (!fs::exists(dstPath)) { fs::create_symlink(fs::read_symlink(srcPath), dstPath); } } catch (const std::exception& e) { std::cerr << "软链接复制失败: " << e.what() << std::endl; } } // 创建硬链接(失败时回退到文件复制) void cpHardLink(const fs::path& srcPath, const fs::path& dstPath) { try { if (!fs::exists(dstPath)) { fs::create_hard_link(srcPath, dstPath); } } catch (const std::exception& e) { std::cerr << "硬链接创建失败,回退到文件复制: " << e.what() << std::endl; cpFile(srcPath, dstPath); } } // 递归复制目录(多线程版本) void cpDirectory(const fs::path& srcPath, const fs::path& dstPath) { try { // 先创建目标目录,确保后续操作路径合法 fs::create_directories(dstPath); std::vector<std::thread> threads; for (const auto& entry : fs::directory_iterator(srcPath)) { const fs::path& srcEntryPath = entry.path(); const fs::path& dstEntryPath = dstPath / srcEntryPath.filename(); if (fs::is_directory(srcEntryPath)) { // 目录递归处理(串行,子目录依赖父目录存在) cpDirectory(srcEntryPath, dstEntryPath); } else if (fs::is_symlink(srcEntryPath)) { // 软链接复制任务加入线程 threads.emplace_back(&cpSoftLink, srcEntryPath, dstEntryPath); } else { // 根据硬链接数量选择复制方式 if (fs::hard_link_count(srcEntryPath) > 1) { threads.emplace_back(&cpHardLink, srcEntryPath, dstEntryPath); } else { threads.emplace_back(&cpFile, srcEntryPath, dstEntryPath); } } } // 等待所有线程完成任务 for (auto& t : threads) { if (t.joinable()) { t.join(); } } } catch (const std::exception& e) { std::cerr << "目录复制失败: " << e.what() << std::endl; } } int main(int argc, char* argv[]) { if (argc != 3) { std::cerr << "用法: " << argv[0] << " <源路径> <目标路径>" << std::endl; return 1; } const fs::path srcPath = argv[1]; const fs::path dstPath = argv[2]; if (!fs::exists(srcPath)) { std::cerr << "源路径不存在: " << srcPath << std::endl; return 1; } cpDirectory(srcPath, dstPath); return 0; }
关键说明
- 线程管理:用
std::vector<std::thread>存储所有复制任务线程,遍历结束后调用join()等待所有线程完成,避免主线程提前退出。 - 硬链接兼容:新增
cpHardLink函数优先创建硬链接,失败时自动回退到文件复制,保证跨设备复制的兼容性。 - 大文件优化:采用1MB缓冲区分块复制,避免一次性加载大文件到内存,提升IO效率与程序稳定性。
- 错误处理:添加
try-catch块捕获异常并输出详细信息,便于调试定位问题。 - 输入校验:main函数增加参数数量与源路径存在性校验,避免非法输入导致程序崩溃。
编译与运行
编译需指定C++17及以上版本(<filesystem>依赖),例如:
g++ -std=c++17 copy_tool.cpp -o copy_tool -pthread
运行时传入源路径与目标路径:
./copy_tool /path/to/source /path/to/destination
内容的提问来源于stack exchange,提问作者Witty Apps
相关产品推荐
相关产品推荐

