class FileGetter{
WIN32_FIND_DATAA found;
HANDLE hfind;
char folderstar[255];
int chk;
public:
FileGetter(char* folder){
sprintf(folderstar,"%s\\*.*",folder);
hfind = FindFirstFileA(folderstar,&found);
//skip .
FindNextFileA(hfind,&found);
}
int getNextFile(char* fname){
//skips .. when called for the first time
chk=FindNextFileA(hfind,&found);
if (chk)
strcpy(fname, found.cFileName);
return chk;
}
};
26
这对我有用 . 如果我不记得来源,我很抱歉 . 它可能来自手册页 .
#include <ftw.h>
int AnalizeDirectoryElement (const char *fpath,
const struct stat *sb,
int tflag,
struct FTW *ftwbuf) {
if (tflag == FTW_F) {
std::string strFileName(fpath);
DoSomethingWith(strFileName);
}
return 0;
}
void WalkDirectoryTree (const char * pchFileName) {
int nFlags = 0;
if (nftw(pchFileName, AnalizeDirectoryElement, 20, nFlags) == -1) {
perror("nftw");
}
}
int main() {
WalkDirectoryTree("some_dir/");
}
将以下 void filefinder() 方法放在代码中并从 main 函数中调用它或编辑函数的使用方法 .
#include <stdio.h>
#include <string.h>
#include "dirent.h"
string path = "C:/folder"; //Put a valid path here for folder
void filefinder()
{
DIR *directory = opendir(path.c_str());
struct dirent *direntStruct;
if (directory != NULL) {
while (direntStruct = readdir(directory)) {
printf("File Name: %s\n", direntStruct->d_name); //If you are using <stdio.h>
//std::cout << direntStruct->d_name << std::endl; //If you are using <iostream>
}
}
closedir(directory);
}
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file */
char d_name[256]; /* filename */
};
#include<io.h>
#include<iostream.h>
#include<string>
using namespace std;
void TraverseFilesUsingDFS(const string& folder_path){
_finddata_t file_info;
string any_file_pattern = folder_path + "\\*";
intptr_t handle = _findfirst(any_file_pattern.c_str(),&file_info);
//If folder_path exsist, using any_file_pattern will find at least two files "." and "..",
//of which "." means current dir and ".." means parent dir
if (handle == -1){
cerr << "folder path not exist: " << folder_path << endl;
exit(-1);
}
//iteratively check each file or sub_directory in current folder
do{
string file_name=file_info.name; //from char array to string
//check whtether it is a sub direcotry or a file
if (file_info.attrib & _A_SUBDIR){
if (file_name != "." && file_name != ".."){
string sub_folder_path = folder_path + "\\" + file_name;
TraverseFilesUsingDFS(sub_folder_path);
cout << "a sub_folder path: " << sub_folder_path << endl;
}
}
else
cout << "file name: " << file_name << endl;
} while (_findnext(handle, &file_info) == 0);
//
_findclose(handle);
}
2
此实现实现了您的目的,使用指定目录的内容动态填充字符串数组 .
int exploreDirectory(const char *dirpath, char ***list, int *numItems) {
struct dirent **direntList;
int i;
errno = 0;
if ((*numItems = scandir(dirpath, &direntList, NULL, alphasort)) == -1)
return errno;
if (!((*list) = malloc(sizeof(char *) * (*numItems)))) {
fprintf(stderr, "Error in list allocation for file list: dirpath=%s.\n", dirpath);
exit(EXIT_FAILURE);
}
for (i = 0; i < *numItems; i++) {
(*list)[i] = stringDuplication(direntList[i]->d_name);
}
for (i = 0; i < *numItems; i++) {
free(direntList[i]);
}
free(direntList);
return 0;
}
24 回答
为什么不使用
glob()
?这是一个非常简单的代码,在
C++11
中使用boost::filesystem
库来获取目录中的文件名(文件夹名称除外):输出如下:
在小而简单的任务中我不使用boost,我使用的 dirent.h 也适用于windows:
它只是一个小的头文件,可以完成你需要的大多数简单的东西,而不需要使用像boost这样的基于模板的大方法(没有冒犯,我喜欢boost!) .
Windows兼容层的作者是Toni Ronkko . 在Unix中,它是标准头 .
UPDATE 2017 :
在C 17中,现在有一种列出文件系统文件的官方方法:
std::filesystem
. 下面的Shreevardhan有一个很好的答案,源代码如下:如果你正在使用C 17方法,请考虑提出他的答案 .
不幸的是,C标准没有以这种方式定义使用文件和文件夹的标准方法 .
由于没有跨平台的方式,最好的跨平台方式是使用诸如boost filesystem module之类的库 .
Cross platform boost method:
来自上面提到的提升页面的来源 .
For Unix/Linux based systems:
您可以使用opendir / readdir / closedir .
上述手册页的源代码 .
For a windows based systems:
您可以使用Win32 API FindFirstFile / FindNextFile / FindClose函数 .
来自上述msdn页面的源代码 .
看看这个使用win32 api的类 . 只需通过提供您希望列表的
foldername
来构造实例,然后调用getNextFile
方法从目录中获取下一个filename
. 我认为它需要windows.h
和stdio.h
.这对我有用 . 如果我不记得来源,我很抱歉 . 它可能来自手册页 .
GNU手册FTW
http://www.gnu.org/software/libc/manual/html_node/Simple-Directory-Lister.html#Simple-Directory-Lister
此外,有时候直接去源(双关语)也是好事 . 通过查看Linux中一些最常见命令的内部结构,您可以学到很多东西 . 我在github上设置了一个GNU coreutils的简单镜像(用于阅读) .
https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c
也许这并不能解决Windows问题,但是使用这些方法可以获得许多使用Unix变体的案例 .
希望有帮助......
这对我有用 . 它只写入所有文件的名称(无路径)的文件 . 然后它读取该txt文件并为您打印 .
尝试使用x-platform方法进行提升
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
或者只是使用您的操作系统特定文件 .
我希望这段代码可以帮到你 .
此答案应适用于使用Visual Studio以及任何其他答案进行此操作时遇到问题的Windows用户 .
针对Windows的dirent.h的Github页面:Github page for dirent.h
原始指令文件:Raw dirent.h File
转到项目并添加新项目(Ctrl Shift A) . 添加头文件(.h)并将其命名为dirent.h .
将Raw dirent.h File代码粘贴到 Headers 中 .
在您的代码中包含“dirent.h” .
将以下
void filefinder()
方法放在代码中并从main
函数中调用它或编辑函数的使用方法 .Shreevardhan的回答非常好 . 但如果你想在c 14中使用它,只需进行更改
namespace fs = experimental::filesystem;
即,
您可以使用std :: experimental :: filesystem :: directory_iterator()获取根目录中的所有文件 . 然后,读取这些路径文件的名称 .
我想,下面的代码片段可用于列出所有文件 .
以下是struct dirent的结构
由于目录的文件和子目录通常存储在树结构中,因此直观的方法是使用DFS算法递归遍历每个目录 . 以下是使用io.h中的基本文件函数在Windows操作系统中的示例 . 您可以在其他平台中替换这些功能 . 我想表达的是DFS的基本思想完全满足了这个问题 .
此实现实现了您的目的,使用指定目录的内容动态填充字符串数组 .
系统调用它!
然后只需阅读该文件 .
编辑:这个答案应该被认为是一个黑客,但它确实有效(如果您无法访问更优雅的解决方案,则以平台特定的方式) .
我试图遵循both answers中给出的示例,可能值得注意的是,似乎
std::filesystem::directory_entry
已被更改为没有<<
运算符的重载 . 而不是std::cout << p << std::endl;
我必须使用以下代码才能编译并使其工作:试图将
p
单独传递给std::cout <<
导致缺少重载错误 .我建议使用
glob
和这个可重复使用的包装器 . 它生成一个vector<string>
,对应于适合glob模式的文件路径:然后可以使用正常的系统通配符模式调用,例如:
C 17现在有std::filesystem::directory_iterator,可以用作
此外,std::filesystem::recursive_directory_iterator也可以迭代子目录 .
对于仅限C的解决方案,请查看此信息 . 它只需要一个额外的 Headers :
https://github.com/cxong/tinydir
与其他选项相比有一些优势
它是可移植的 - 包装POSIX dirent和Windows FindFirstFile
它在可用的地方使用
readdir_r
,这意味着它(通常)线程安全通过相同的
UNICODE
宏支持Windows UTF-16这是C90所以即使非常古老的编译器也可以使用它
我想分享一些内容并感谢您阅读材料 . 玩这个功能有点了解它 . 你可能会喜欢它 . e表示扩展,p表示路径,s表示路径分隔符 .
如果传递的路径没有结束分隔符,则会将分隔符附加到路径 . 对于扩展,如果输入空字符串,则该函数将返回其名称中没有扩展名的任何文件 . 如果输入单个星,则将返回目录中的所有文件 . 如果e长度大于0但不是单个*,那么如果e在零位置没有包含点,则将在e前面加一个点 .
对于返回值 . 如果返回零长度映射,则找不到任何内容,但目录打开正常 . 如果索引999可以从返回值获得,但 Map 大小只有1那么这意味着打开目录路径时出现问题 .
请注意,为了提高效率,此功能可以分为3个较小的功能 . 最重要的是,您可以创建一个调用函数,它将根据输入检测它将调用哪个函数 . 为什么效率更高?如果你要 grab 文件的所有内容,那么执行该方法时,为抓取所有文件而构建的子函数将只抓取所有文件,并且每次找到文件时都不需要评估任何其他不必要的条件 .
当你抓取没有扩展名的文件时,这也适用 . 用于此目的的特定构建函数仅在找到的对象是文件时评估天气,然后评估文件名是否在其中具有点 .
如果你只读取没有那么多文件的目录,那么保存可能不会太多 . 但是如果你正在阅读大量的目录,或者如果该目录有几十万个文件,那么这可能是一个巨大的节省 .
One function is enough, you don't need to use any 3rd-party library (for Windows).
PS:如@Sebastian所述,您可以将
*.*
更改为*.ext
,以便仅获取该目录中的EXT文件(即特定类型) .