首页 > 解决方案 > 使用 std::filesystem 和多线程搜索文件

问题描述

我编写了一个程序,使用 std::filesystem 在系统上按名称搜索文件(使用 std::filesystem::recursive_directory_iterator 进行递归搜索)。如果我只使用一个主线程,执行时间约为 1 秒,如果我从 Linux 上的根(“/”)目录开始,它可以正常工作。问题:当我尝试使用多个线程运行该程序时,我得到了中止(核心转储)和文件系统错误:递归目录迭代器无法打开目录:不是目录。我想运行该功能

bool SearchFile::find_file_in_directory(const std::string file_name, fs::path path) 

同时在 8 个线程中但具有不同的参数(路径参数将是另一个)。我尝试以这种方式实现多线程:计算系统上所有现有文件的数量,然后将这个数字除以线程数,并给每个线程入口目录以开始搜索。我也有自己的类来处理名为 SearchFile (sf) 的文件。下面列出的代码:

一个线程的第一种方法(它按我的需要工作):

bool SearchFile::find_file_from_directory(const std::string file_name,
                                          fs::path path) {
  if (fs::is_directory(path))
    for (auto &p : fs::recursive_directory_iterator(
             path, fs::directory_options::skip_permission_denied)) {
      path = p;
      if (path.filename() == file_name) {
        curr_path = path;
        return true;
      } else {
        // uncomment this line to see how the function search file
        // std::cout<<path<<"\n";
        continue;
      }
    }
  else
    std::cout << "Entered path is not a directory\n";

  return false;

  std::cout << "File doesn`t exist\n";
  return false;
}

我使用的 SearchFile 方法:

bool SearchFile::find_file_in_directory(const std::string file_name,
                                        fs::path path) {
  if (fs::is_directory(path))
    path /= file_name;
  if (fs::exists(path)) {
    return true;
  } else
    std::cout << "Entered path is not a directory\n";
  return false;

  std::cout << "File doesn`t exist\n";
  return false;
}

u_int SearchFile::get_num_of_files_recursively(const fs::path path) {
  u_int num = 0;
  if (fs::is_directory(path)) {
    for (fs::recursive_directory_iterator it(
             path, fs::directory_options::skip_permission_denied);
         it != fs::recursive_directory_iterator(); ++it) {
      num++;
    }
  } else {
    std::cout << "Entered path is not a directory\n";
    return 0;
  }
  return num;
}

主文件

#include <iostream>
#include <string>
#include <thread>
//#include "library/searchfile.h"
#include <condition_variable>
#include <fstream>
#include <vector>
//#pragma once
#include <filesystem>

SearchFile sf;
std::condition_variable cv;
std::vector<fs::path> arr;

void do_division(const fs::path path, const u_int times) {
  u_int files_num = sf.get_num_of_files_recursively(path),
        part = files_num / times;
  u_int i = 0;
  arr.push_back(path);
  for (fs::recursive_directory_iterator it(path, fs::directory_options::skip_permission_denied);
       it != fs::recursive_directory_iterator(); ++it) {
    if (i == part) {
      arr.push_back(it->path());
      part += part;
    }
    i++;
  }
}

void do_job(const fs::path path, const std::string name) noexcept {
  for (auto &p : fs::recursive_directory_iterator(path, fs::directory_options::skip_permission_denied)) {
    std::cout << std::this_thread::get_id() << " - " << p.path() << "\n";

    if (sf.find_file_in_directory(name, p.path())) {
      cv.notify_all();
      std::fstream f;
      std::string path = p.path().string();
      f.open(path);
      f << path;
      f.close();
      return;
    }
  }
}

int main() {
  std::string filename = "MyFile.txt";
  std::string path = "/";

  do_division("/", 8);

  while (1) {
    std::thread t1(do_job, arr[0], filename);
    t1.detach();

    std::thread t2(do_job, arr[1], filename);
    t2.detach();

    std::thread t3(do_job, arr[2], filename);
    t3.detach();

    std::thread t4(do_job, arr[3], filename);
    t4.detach();

    std::thread t5(do_job, arr[4], filename);
    t5.detach();

    std::thread t6(do_job, arr[5], filename);
    t6.detach();

    std::thread t7(do_job, arr[6], filename);
    t7.detach();

    std::thread t8(do_job, arr[7], filename);
    t8.detach();
  }
  return 0;
}

也许这不是解决我问题的好方法,但我只是一个初学者。

标签: c++multithreadingfile-searchstd-filesystem

解决方案


推荐阅读