【问题标题】:Read all files from a folder c++从文件夹 c++ 中读取所有文件
【发布时间】:2013-12-12 13:12:49
【问题描述】:

我有一个从文件夹中读取图像的程序。我正在使用 for 访问文件的所有索引并将它们存储到向量中:

    for(int i=0; i<labels.size(); i++){

    ostringstream stringStream;
    stringStream << setfill ('0') << setw (4) << i;
    num2string = stringStream.str();

    string img = "C:\\opencvAssets/detected/BioID_"+num2string+".pgm";
    //cout<< img <<" \n";
    images.push_back(imread(img, CV_LOAD_IMAGE_GRAYSCALE));  //labels.push_back(i);
}

我遇到了一些麻烦,因为文件夹中故意丢失了一些文件。因此,for 方法是禁止的。如何读取所有文件并将它们存储到向量中??

【问题讨论】:

  • 无法使用标准库获取目录的内容。但是我怀疑 boost 可能会为此提供一个抽象。
  • 您想检查具有给定字符串名称的文件是否存在,对吗?看看这个stackoverflow.com/questions/12774207/…或者这个stackoverflow.com/questions/18320486/…
  • 如果您有权访问 boost,请使用文件系统库中的目录迭代器。
  • 我也遇到了同样的问题,用dirent和fnmatch解决了。

标签: c++ file directory


【解决方案1】:

首先你需要扫描目录并获取文件:

您可以使用FindFirstFileFindNextFile

bool find_files(){
  WIN32_FIND_DATA FindFileData;
  string img = "C:\\opencvAssets/detected/BioID_*.pgm";
  HANDLE hFind = FindFirstFile(img.c_str(), &FindFileData);
  if(hFind == INVALID_HANDLE_VALUE){
    return false;
  } 
  else do{
    cout<<FindFileData.cFileName<<endl;
  } while (FindNextFile(hFind, &FindFileData));
  FindClose(hFind);
  return true;
}

编辑:

对于 Linux: 您可以查看 here 如何迭代目录,但最好的方法是使用 forkexecv 运行 find 命令并使用管道获取输出. like this

EDIT2 从终端你可以找到所有这样的文件:

find path/to/dir -name 'BioID_*.pgm'

因此您可以使用重定向到文件或使用forkexecv 来运行它。如果您不是一个简单的解决方案,请使用 system 中的它并重定向到一个文件,并使用所有已建立的文件名打开该文件。

【讨论】:

  • 这仅适用于 Windows。如果你在其他平台上不需要,没关系。
  • 是的,但他给了一个恒定的 Windows 路径,所以我不敢相信他想要其他操作系统。
  • 我真的想要win和linux都想要!!路径只是一个例子!!
  • 我正在尝试使用stackoverflow.com/questions/12774207/… 中的方法,使用exists 函数.. bool exists(const std::string& name)。我对调用如何存在函数有点困惑。它必须是函数的参数??
  • 我不会为此使用 fork()。
【解决方案2】:

补丁:

if (Cv::mat m = imread(img, CV_LOAD_IMAGE_GRAYSCALE)) images.push_back(m); 

但对于严肃的任务,请使用 boost::filesystem 来限制对实际存在的文件的访问。

【讨论】:

    【解决方案3】:

    在 Linux 上你可以做到:

    1) 创建一个 DIR 指针, 使用 opendir() 打开目录

    DIR *ptr = opendir( path_of_directory );

    2) 创建 struct dirent 指针, 使用 readdir() 从目录中读取文件;

    struct dirent *ptr = readdir(ptr); //传递DIR指针

    3) 在 while 循环中运行上述代码。 Push_back 将向量中的数据作为引用传递给此函数或返回向量。

    4) 确保 "."并且“..”不是文件,所以不要将其推送到向量中。 // 要检查这一点,您可以使用 std::strcmp( dirent_pointer->d_name, "." ) == 0 所以.. if( !std::strcmp( ptr->d_name, "." ) == 0 )

    希望对你有帮助

    【讨论】:

    • 最好检查标准文件的类型:dirent_pointer->d_type == DT_REG
    【解决方案4】:

    在 SHR 的示例中,您需要扫描目录并获取文件。 您可以在每个 Unix 平台上使用特定于 Windows 的实现,或 dirent.h 中的函数。

    有关 Unix 上的 dirent.h 的更多信息,请参阅this question

    【讨论】:

      【解决方案5】:

      您可以使用 boost::filesystem。但是,这不是一个只有头文件的库,您可能需要不与外部库链接,或者这样做可能非常不方便。 在 Windows 上(看起来像你)我喜欢使用这个类来获取所有匹配给定模式的文件名。

      #pragma once
      #include <string>
      #include <vector>
      #include <windows.h>
      
      #pragma comment(lib, "User32.lib")
      
      #undef tstring
      #undef tcout
      #if defined(_UNICODE) || defined(UNICODE)
      #define tstring std::wstring
      #define tcout std::wcout
      #else
      #define tstring std::string
      #define tcout std::cout
      #endif
      
      class FileFinder {
        WIN32_FIND_DATA ffd;
        HANDLE _handle;
      
      public:
        FileFinder(LPCTSTR pattern) { _handle = FindFirstFile(pattern, &ffd); }
        ~FileFinder() { FindClose(_handle); }
        const TCHAR *FindFirst() const {
          return _handle != INVALID_HANDLE_VALUE ? ffd.cFileName : nullptr;
        }
        const TCHAR *FindNext() {
          return FindNextFile(_handle, &ffd) ? ffd.cFileName : nullptr;
        }
        std::vector<tstring> GetAllNames() {
          std::vector<tstring> result;
          for (auto name = FindFirst(); name; name = FindNext())
            result.push_back(name);
          return result;
        }
      };
      

      它遵循 RAII 范式,不会因异常而泄漏资源。 它的用法示例可能是这样的。

      #include <tchar.h>
      #include <iostream>
      #include "FileFinder.h"
      
      int _tmain(int argc, TCHAR *argv[]) {
        DWORD dwError = 0;
      
        if (argc != 2) {
          _tprintf(TEXT("\nUsage: %s <directory name>\n"), argv[0]);
          return -1;
        }
      
        tstring pattern(argv[1]);
        pattern.erase(pattern.find_last_not_of(TEXT("\\")) + 1);
        pattern += TEXT("\\*.pgm");
        if (pattern.length() > MAX_PATH) {
          _tprintf(TEXT("\nDirectory path is too long.\n"));
          return -1;
        }
        FileFinder finder(pattern.c_str());
        auto files = finder.GetAllNames();
        for (const auto &f : files)
          tcout << f << std::endl;
        return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-06
        • 1970-01-01
        • 2020-03-03
        • 2013-06-20
        • 2021-01-08
        • 1970-01-01
        • 2021-04-03
        • 2010-12-23
        相关资源
        最近更新 更多