从文件夹 C++ 中读取所有文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20544532/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Read all files from a folder c++
提问by Jose Ramon
I am having a program which reads images from a folder. I am using a for to access all the index of the files and store them into a vector:
我有一个从文件夹中读取图像的程序。我正在使用 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);
}
I am having some troubles, since some of the files delibrately is missing from the folder. Thus, for approach is prohibitive. How can I read all the files and store them into a vector??
我遇到了一些麻烦,因为文件夹中故意丢失了一些文件。因此, for 方法是禁止的。如何读取所有文件并将它们存储到向量中?
回答by SHR
First you need to scan directory and get files:
首先你需要扫描目录并获取文件:
You can use FindFirstFileand FindNextFile
您可以使用FindFirstFile和FindNextFile
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;
}
EDIT:
编辑:
For Linux:you can check herehow to iterate directory, but the best way is to use fork
and execv
to run a find
command and get output with pipes. like this
对于 Linux:您可以在此处查看如何迭代目录,但最好的方法是使用fork
和execv
运行find
命令并通过管道获取输出。像这样
EDIT2From terminal you can find all files like this:
EDIT2从终端你可以找到这样的所有文件:
find path/to/dir -name 'BioID_*.pgm'
find path/to/dir -name 'BioID_*.pgm'
So you can run it with redirect to file or use fork
and execv
. If you wan't a simple solution use it from system
with redirect to a file, and open the file with all the founded file names.
因此,您可以通过重定向到文件或使用fork
and来运行它execv
。如果您不想使用简单的解决方案,请使用system
重定向到文件,并使用所有已建立的文件名打开该文件。
回答by CapelliC
a patch:
一个补丁:
if (Cv::mat m = imread(img, CV_LOAD_IMAGE_GRAYSCALE)) images.push_back(m);
but for serious tasks use boost::filesystem to restrict access to actually existing files.
但是对于严肃的任务,使用 boost::filesystem 来限制对实际存在的文件的访问。
回答by Biraj Borah
On Linux you can do it :
在 Linux 上你可以这样做:
1) Create a DIR pointer, Open the directory using opendir()
1) 创建一个 DIR 指针,使用 opendir() 打开目录
DIR *ptr = opendir( path_of_directory );
DIR *ptr = opendir( path_of_directory );
2) Create struct dirent pointer, Read the file from directory using readdir();
2) 创建 struct dirent 指针,使用 readdir() 从目录中读取文件;
struct dirent *ptr = readdir(ptr); //pass the DIR pointer
struct dirent *ptr = readdir(ptr); //传递DIR指针
3) Run the above in a while loop. Push_back the data in a vector which is passed to this function as reference or return the vector.
3)在while循环中运行上面的内容。Push_back 将向量中的数据作为参考传递给此函数或返回向量。
4) Make sure that "." and ".." is not a file, so dont push that in vector. // To check this you can use std::strcmp( dirent_pointer->d_name, "." ) == 0 so.. if( !std::strcmp( ptr->d_name, "." ) == 0 )
4) 确保“.” 并且“..”不是文件,因此不要将其推入向量中。// 要检查这一点,您可以使用 std::strcmp( dirent_pointer->d_name, "." ) == 0 so.. if( !std::strcmp( ptr->d_name, "." ) == 0 )
Hope that helps
希望有帮助
回答by G B
As in the example by SHR, you need to scan the directory and get files. You can use the Windows-specific implementation, or the functions in dirent.hon every Unix platform.
在 SHR 的示例中,您需要扫描目录并获取文件。您可以在每个 Unix 平台上使用 Windows 特定的实现或dirent.h 中的函数。
See this questionfor more information about dirent.h on Unix.
有关Unix 上 dirent.h 的更多信息,请参阅此问题。
回答by Vlad
You can use boost::filesystem. However, this is not a header only library and you may have requirements not to link with external libraries or it may be very inconvenient to do so. On Windows (which looks like you are) I like to use this class to get all the filenames matching given pattern.
您可以使用 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;
}
};
It follows RAII paradigm and will not leak resources due to an exception. Example of it's usage could be like this.
它遵循 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;
}