You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

关键说明

  1. 线程管理:用std::vector<std::thread>存储所有复制任务线程,遍历结束后调用join()等待所有线程完成,避免主线程提前退出。
  2. 硬链接兼容:新增cpHardLink函数优先创建硬链接,失败时自动回退到文件复制,保证跨设备复制的兼容性。
  3. 大文件优化:采用1MB缓冲区分块复制,避免一次性加载大文件到内存,提升IO效率与程序稳定性。
  4. 错误处理:添加try-catch块捕获异常并输出详细信息,便于调试定位问题。
  5. 输入校验: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 11:21:04