如何使用C或C ++获取目录中的文件列表?


592

如何从C或C ++代码内部确定目录中的文件列表?

我不允许执行ls命令并从程序内部解析结果。


7
这是609236
基督


1
@chrish-是的,但这是经典的“我不允许执行'ls'”!这正是我对计算机科学大一的感觉。; D <3 x
James Bedford

1
C和C ++语言不同。因此,在两种语言中,完成此任务的过程将有所不同。请选择一个并相应地重新标记。
MD XF

2
这些语言(除了自C ++ 17以来的C ++)都没有目录的概念-因此,任何答案都可能取决于您的OS或您可能使用的任何抽象库。
Toby Speight '18

Answers:


809

在小的简单任务中,我不使用boost,而是使用dirent.h,它也可用于Windows:

DIR *dir;
struct dirent *ent;
if ((dir = opendir ("c:\\src\\")) != NULL) {
  /* print all the files and directories within directory */
  while ((ent = readdir (dir)) != NULL) {
    printf ("%s\n", ent->d_name);
  }
  closedir (dir);
} else {
  /* could not open directory */
  perror ("");
  return EXIT_FAILURE;
}

它只是一个很小的头文件,不需要使用boost这样的基于模板的大方法就可以完成您所需的大多数简单操作(不犯罪,我喜欢boost!)。

Windows兼容性层的作者是Toni Ronkko。在Unix中,它是一个标准头。

更新2017

在C ++ 17中,现在有一种列出文件系统文件的官方方法:std::filesystem。下面的源代码在Shreevardhan中有一个很好的答案:

#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

int main()
{
    std::string path = "/path/to/directory";
    for (const auto & entry : fs::directory_iterator(path))
        std::cout << entry.path() << std::endl;
}

5
@ArtOfWarfare:回答此问题时甚至没有创建tinydir。它还是dirent(POSIX)和FindFirstFile(Windows)的包装,而dirent.h仅包装Windows的dirent。我认为这是一种个人品味,但dirent.h感觉更像是一种标准
彼得·帕克

7
@JoshC:因为* ent只是内部表示形式的返回指针。通过关闭目录,您也将消除* ent。由于* ent仅用于阅读,我认为这是一个理智的设计。
彼得·帕克

42
人们变得真实!这是2009年以来的一个问题,甚至没有提到VS。因此,不要批评您的完全专有(虽然非常不错)的IDE不支持数百年来的旧OS标准。我的回答还说,这是Windows的“可用”,从现在到现在一直没有“包含”在任何IDE中……我很确定您可以下载dirent并将其放在其中的include dir和voila中。
彼得·帕克

6
答案是误导的。它应以:“ ...我使用dirent.h也存在 Windows开源兼容性层 ”。
rustyx

10
在C ++ 14中std::experimental::filesystem,存在std::filesystem。请参阅下面的Shreevardhan的答案。因此,无需第三方库。
罗伊·丹顿

346

C ++ 17现在有一个std::filesystem::directory_iterator,可以用作

#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

int main() {
    std::string path = "/path/to/directory";
    for (const auto & entry : fs::directory_iterator(path))
        std::cout << entry.path() << std::endl;
}

同样,std::filesystem::recursive_directory_iterator也可以迭代子目录。


27
AFAIK也可以在C ++ 14中使用,但仍处于实验阶段:namespace fs = std::experimental::filesystem;。看来工作正常。
PeterK '16

7
这应该是当前使用的首选答案(从C ++ 17开始)
green diod

4
传递std::filesystem::path给时请注意std::cout,输出中包括引号。为避免这种情况,.string()请在路径后附加执行显式而不是隐式转换(在此处std::cout << p.string() << std::endl;)。范例:coliru.stacked-crooked.com/view?id = a55ea60bbd36a8a3
Roi Danton

2
文件名中的非ASCII字符呢?不应std::wstring使用,或者迭代器的类型是什么?
anddero '18

2
我不确定我是否一个人,但是如果不链接-lstdc++fs,我会得到一个SIGSEGV (Address boundary error)。我在文档中找不到任何需要的地方,而且链接器也没有提供任何线索。这对g++ 8.3.0和都有效clang 8.0.0-3。是否有人对在docs / specs中指定类似内容的地方有任何见解?
swalog

229

不幸的是,C ++标准并未定义以这种方式使用文件和文件夹的标准方式。

由于没有跨平台方式,因此最好的跨平台方式是使用诸如boost filesystem module之类的库。

跨平台提升方法:

给定目录路径和文件名的以下函数以递归方式在目录及其子目录中搜索文件名,并返回布尔值和找到的文件路径(如果成功)。

bool find_file(const path & dir_path,         // in this directory,
               const std::string & file_name, // search for this name,
               path & path_found)             // placing path here if found
{
    if (!exists(dir_path)) 
        return false;

    directory_iterator end_itr; // default construction yields past-the-end

    for (directory_iterator itr(dir_path); itr != end_itr; ++itr)
    {
        if (is_directory(itr->status()))
        {
            if (find_file(itr->path(), file_name, path_found)) 
                return true;
        }
        else if (itr->leaf() == file_name) // see below
        {
            path_found = itr->path();
            return true;
        }
    }
    return false;
}

来自上述提升页面的资源。

对于基于Unix / Linux的系统:

您可以使用opendir / readdir / closedir

在目录中搜索条目``名称''的示例代码为:

len = strlen(name);
dirp = opendir(".");
while ((dp = readdir(dirp)) != NULL)
        if (dp->d_namlen == len && !strcmp(dp->d_name, name)) {
                (void)closedir(dirp);
                return FOUND;
        }
(void)closedir(dirp);
return NOT_FOUND;

以上手册页中的源代码。

对于基于Windows的系统:

您可以使用Win32 API FindFirstFile / FindNextFile / FindClose函数。

以下C ++示例向您展示了FindFirstFile的最少使用。

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

void _tmain(int argc, TCHAR *argv[])
{
   WIN32_FIND_DATA FindFileData;
   HANDLE hFind;

   if( argc != 2 )
   {
      _tprintf(TEXT("Usage: %s [target_file]\n"), argv[0]);
      return;
   }

   _tprintf (TEXT("Target file is %s\n"), argv[1]);
   hFind = FindFirstFile(argv[1], &FindFileData);
   if (hFind == INVALID_HANDLE_VALUE) 
   {
      printf ("FindFirstFile failed (%d)\n", GetLastError());
      return;
   } 
   else 
   {
      _tprintf (TEXT("The first file found is %s\n"), 
                FindFileData.cFileName);
      FindClose(hFind);
   }
}

来自上述msdn页面的源代码。


用法:FindFirstFile(TEXT("D:\\IMAGE\\MYDIRECTORY\\*"), &findFileData);
КонстантинВан

7
对于C ++ 14,存在std::experimental::filesystem,对于C ++ 17 std::filesystem,具有与boost类似的功能(库是从boost派生的)。请参阅下面的Shreevardhan的答案。
罗伊·丹顿

对于Windows,请参阅docs.microsoft.com/zh-cn/windows/desktop/FileIO/…了解详细信息
FindOutIslamNow

90

一个功能就足够了,您不需要使用任何第三方库(对于Windows)。

#include <Windows.h>

vector<string> get_all_files_names_within_folder(string folder)
{
    vector<string> names;
    string search_path = folder + "/*.*";
    WIN32_FIND_DATA fd; 
    HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd); 
    if(hFind != INVALID_HANDLE_VALUE) { 
        do { 
            // read all (real) files in current folder
            // , delete '!' read other 2 default folder . and ..
            if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
                names.push_back(fd.cFileName);
            }
        }while(::FindNextFile(hFind, &fd)); 
        ::FindClose(hFind); 
    } 
    return names;
}

PS:如@Sebastian所述,您可以更改*.**.ext,以便仅在该目录中获取EXT文件(即特定类型)。


20
此解决方案(特定于平台)。这就是您需要第三方库的原因。
kraxor 2014年

9
@kraxor是的,它仅适用于Windows,但OP从未要求拥有跨平台解决方案。顺便说一句,我总是喜欢选择不使用第3库的东西(如果可能)。
herohuyongtao 2014年

7
@herohuyongtao OP从未指定平台,而为一个通用问题提供与平台高度相关的解决方案可能会产生误导。(如果有一个仅适用于PlayStation 3的单行解决方案呢?这是一个很好的答案吗?)我看到您编辑了答案以声明它仅适用于Windows,我想这样很好。
kraxor 2014年

1
@herohuyongtao OP提到他无法解析ls,这意味着他可能在unix上。
托马斯

2
我最终使用a std::vector<std::wstring>,然后fileName.c_str()代替了不会编译的字符串向量。
PerryC '16

51

对于纯C解决方案,请检查一下。它只需要一个额外的标题:

https://github.com/cxong/tinydir

tinydir_dir dir;
tinydir_open(&dir, "/path/to/dir");

while (dir.has_next)
{
    tinydir_file file;
    tinydir_readfile(&dir, &file);

    printf("%s", file.name);
    if (file.is_dir)
    {
        printf("/");
    }
    printf("\n");

    tinydir_next(&dir);
}

tinydir_close(&dir);

相对于其他选项的一些优势:

  • 它是便携式的-包装POSIX dirent和Windows FindFirstFile
  • 它使用readdir_r可用的地方,这意味着(通常)是线程安全的
  • 通过相同的UNICODE宏支持Windows UTF-16
  • 它是C90,因此即使是非常古老的编译器也可以使用它

2
非常好的建议。我没有测试它在Windows计算机上还没有,但它出色的作品在OS X
ArtOfWarfare

该库不支持std :: string,因此您不能将file.c_str()传递给tinydir_open。在这种情况下,在msvc 2015上编译期间会出现错误C2664。
Stepan Yakovenko

33

我建议使用glob此可重复使用的包装器。它会生成一个vector<string>与glob模式匹配的文件路径:

#include <glob.h>
#include <vector>
using std::vector;

vector<string> globVector(const string& pattern){
    glob_t glob_result;
    glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
    vector<string> files;
    for(unsigned int i=0;i<glob_result.gl_pathc;++i){
        files.push_back(string(glob_result.gl_pathv[i]));
    }
    globfree(&glob_result);
    return files;
}

然后可以使用常规系统通配符模式调用该模式,例如:

vector<string> files = globVector("./*");

2
测试glob()返回零。
卡米尔·古德塞内

我想按照您的建议使用glob.h。但是,我仍然不能包含.h文件:它说No such file or directory。你能告诉我如何解决这个问题吗?
Tofuw '16

请注意,此例程仅深入一层(无递归)。它也不会做快速的检查,以确定它是否是一个文件或目录,您可以通过切换很容易地做到GLOB_TILDEGLOB_TILDE | GLOB_MARK再检查在一个斜线结束路径。如果需要,您必须对其进行任何修改。
Volomike '16

该跨平台兼容吗?
Nikhil Augustine '18

不幸的是,您无法通过找到统一隐藏的文件glob
LmTinyToon

23

这是C++11使用boost::filesystem库获取目录中文件名的非常简单的代码(不包括文件夹名):

#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;

int main()
{
    path p("D:/AnyFolder");
    for (auto i = directory_iterator(p); i != directory_iterator(); i++)
    {
        if (!is_directory(i->path())) //we eliminate directories
        {
            cout << i->path().filename().string() << endl;
        }
        else
            continue;
    }
}

输出如下:

file1.txt
file2.dat

嗨,我在哪里可以得到这个图书馆?
亚历山大·莱昂六世

2
@Alexander De Leon:您可以在其网站boost.org上获得此库,首先阅读入门指南,然后使用其boost::filesystemboost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htm
不良

23

为什么不使用glob()

#include <glob.h>

glob_t glob_result;
glob("/your_directory/*",GLOB_TILDE,NULL,&glob_result);
for(unsigned int i=0; i<glob_result.gl_pathc; ++i){
  cout << glob_result.gl_pathv[i] << endl;
}

如果您解释必需的包含项,这可能是一个更好的答案。
Volomike '16

2
测试glob()返回零!
orbitcowboy

这是很好的,当你知道你正在寻找如* .TXT文件
克敏周

20

我认为,以下代码段可用于列出所有文件。

#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>

static void list_dir(const char *path)
{
    struct dirent *entry;
    DIR *dir = opendir(path);
    if (dir == NULL) {
        return;
    }

    while ((entry = readdir(dir)) != NULL) {
        printf("%s\n",entry->d_name);
    }

    closedir(dir);
}

以下是结构差异的结构

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

我想要这个。
selfboot '19


8

签出使用win32 API的此类。只需通过提供foldername您要从中列出的实例来构造一个实例,然后调用该getNextFile方法以filename从目录中获取下一个实例。我认为这需要windows.hstdio.h

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

};

6

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变体的情况。

希望有帮助...


5

Shreevardhan的答案很棒。但是,如果要在c ++ 14中使用它,只需进行更改namespace fs = experimental::filesystem;

#include <string>
#include <iostream>
#include <filesystem>

using namespace std;
namespace fs = experimental::filesystem;

int main()
{
    string path = "C:\\splits\\";
    for (auto & p : fs::directory_iterator(path))
        cout << p << endl;
    int n;
    cin >> n;
}

4
char **getKeys(char *data_dir, char* tablename, int *num_keys)
{
    char** arr = malloc(MAX_RECORDS_PER_TABLE*sizeof(char*));
int i = 0;
for (;i < MAX_RECORDS_PER_TABLE; i++)
    arr[i] = malloc( (MAX_KEY_LEN+1) * sizeof(char) );  


char *buf = (char *)malloc( (MAX_KEY_LEN+1)*sizeof(char) );
snprintf(buf, MAX_KEY_LEN+1, "%s/%s", data_dir, tablename);

DIR* tableDir = opendir(buf);
struct dirent* getInfo;

readdir(tableDir); // ignore '.'
readdir(tableDir); // ignore '..'

i = 0;
while(1)
{


    getInfo = readdir(tableDir);
    if (getInfo == 0)
        break;
    strcpy(arr[i++], getInfo->d_name);
}
*(num_keys) = i;
return arr;
}

3

希望这段代码对您有所帮助。

#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

string wchar_t2string(const wchar_t *wchar)
{
    string str = "";
    int index = 0;
    while(wchar[index] != 0)
    {
        str += (char)wchar[index];
        ++index;
    }
    return str;
}

wchar_t *string2wchar_t(const string &str)
{
    wchar_t wchar[260];
    int index = 0;
    while(index < str.size())
    {
        wchar[index] = (wchar_t)str[index];
        ++index;
    }
    wchar[index] = 0;
    return wchar;
}

vector<string> listFilesInDirectory(string directoryName)
{
    WIN32_FIND_DATA FindFileData;
    wchar_t * FileName = string2wchar_t(directoryName);
    HANDLE hFind = FindFirstFile(FileName, &FindFileData);

    vector<string> listFileNames;
    listFileNames.push_back(wchar_t2string(FindFileData.cFileName));

    while (FindNextFile(hFind, &FindFileData))
        listFileNames.push_back(wchar_t2string(FindFileData.cFileName));

    return listFileNames;
}

void main()
{
    vector<string> listFiles;
    listFiles = listFilesInDirectory("C:\\*.txt");
    for each (string str in listFiles)
        cout << str << endl;
}

4
-1。string2wchar_t返回局部变量的地址。另外,您可能应该使用WinAPI中提供的转换方法,而不要编写自己的转换方法。
Daniel Kamil Kozar 2013年

3

该实现实现了您的目的,即使用指定目录的内容动态填充字符串数组。

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

我怎么称呼它?当我尝试在第一个if块上运行此功能时,我遇到了段错误。我用char **list; int numItems; exploreDirectory("/folder",list, numItems);
Hal T

2

这对我有用。很抱歉,如果我不记得来源。它可能来自手册页。

#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/");
}

2

您可以使用std :: experimental :: filesystem :: directory_iterator()获得根目录中所有文件的直接文件。然后,读取这些路径文件的名称。

#include <iostream>
#include <filesystem>
#include <string>
#include <direct.h>
using namespace std;
namespace fs = std::experimental::filesystem;
void ShowListFile(string path)
{
for(auto &p: fs::directory_iterator(path))  /*get directory */
     cout<<p.path().filename()<<endl;   // get file name
}

int main() {

ShowListFile("C:/Users/dell/Pictures/Camera Roll/");
getchar();
return 0;
}

2

该答案适用于在其他任何答案下都无法使用Visual Studio的Windows用户。

  1. 从github页面下载dirent.h文件。但是最好只使用Raw dirent.h文件并按照下面的步骤操作(这是我如何使它工作)。

    适用于Windows 的dirent.h的Github页面:适用于dirent.h的Github页面

    原始Dirent文件:Raw dirent.h文件

  2. 转到您的项目,然后添加一个新项目(Ctrl+ Shift+ A)。添加一个头文件(.h),并将其命名为dirent.h。

  3. Raw dirent.h文件代码粘贴到标头中。

  4. 在代码中包含“ dirent.h”。

  5. 将以下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);
    }

1

系统调用吧!

system( "dir /b /s /a-d * > file_names.txt" );

然后,只需读取文件即可。

编辑:这个答案应该被认为是黑客,但是如果您无法获得更优雅的解决方案,它的确可以工作(尽管以特定于平台的方式)。


7
我不允许执行“ ls”命令并从程序中解析结果。我知道会有人发送这样的信息……
yyny 2015年

1

由于目录的文件和子目录通常以树结构存储,因此一种直观的方法是使用DFS算法递归遍历它们中的每一个。这是Windows操作系统中使用io.h中的基本文件功能的示例。您可以在其他平台上替换这些功能。我要表达的是DFS的基本思想完全可以解决这个问题。

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

1

我试图按照两个 答案中给出的示例进行操作,可能值得一提的是,它似乎std::filesystem::directory_entry已经更改为没有<<运算符的重载。而不是std::cout << p << std::endl;我不得不使用以下内容来进行编译并使之正常工作:

#include <iostream>
#include <filesystem>
#include <string>
namespace fs = std::filesystem;

int main() {
    std::string path = "/path/to/directory";
    for(const auto& p : fs::directory_iterator(path))
        std::cout << p.path() << std::endl;
}

试图p自行传递std::cout <<导致丢失的过载错误。


1

在herohuyongtao和其他一些帖子的基础上:

http://www.cplusplus.com/forum/general/39766/

FindFirstFile的预期输入类型是什么?

怎么把wstring转换成string?

这是Windows解决方案。

由于我想传递std :: string并返回一个字符串向量,因此我不得不进行几次转换。

#include <string>
#include <Windows.h>
#include <vector>
#include <locale>
#include <codecvt>

std::vector<std::string> listFilesInDir(std::string path)
{
    std::vector<std::string> names;
    //Convert string to wstring
    std::wstring search_path = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(path);
    WIN32_FIND_DATA fd;
    HANDLE hFind = FindFirstFile(search_path.c_str(), &fd);
    if (hFind != INVALID_HANDLE_VALUE) 
    {
        do 
        {
            // read all (real) files in current folder
            // , delete '!' read other 2 default folder . and ..
            if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 
            {
                //convert from wide char to narrow char array
                char ch[260];
                char DefChar = ' ';
                WideCharToMultiByte(CP_ACP, 0, fd.cFileName, -1, ch, 260, &DefChar, NULL);
                names.push_back(ch);
            }
        } 
        while (::FindNextFile(hFind, &fd));
        ::FindClose(hFind);
    }
    return names;
}

如果你知道你将只有使用多字节你可以使用 WIN32_FIND_DATAAFindFirstFileAFindNextFileA。这样就无需将结果转换为多字节或将输入转换为unicode。
基兰·蒂拉克

0

我想分享一些内容,感谢您的阅读材料。试一试该功能,以了解它。您可能会喜欢。e表示扩展,p表示路径,s表示路径分隔符。

如果通过路径时没有结束分隔符,则分隔符将附加到路径中。对于扩展名,如果输入一个空字符串,则该函数将返回名称中没有扩展名的任何文件。如果输入单个星号,则将返回目录中的所有文件。如果e长度大于0但不是单个*,则如果e在零位置不包含点,则将在e之前加点。

对于返回值。如果返回零长度的映射,则找不到任何内容,但目录已打开。如果返回值中有可用的索引999,但映射大小仅为1,则意味着打开目录路径存在问题。

注意,为了提高效率,可以将此功能分为3个较小的功能。最重要的是,您可以创建一个调用程序函数,该函数将根据输入检测要调用的函数。为什么这样更有效?说如果要捕获文件中的所有内容,则使用该方法为捕获所有文件而构建的子功能将仅捕获所有文件,并且不需要在每次找到文件时都评估任何其他不必要的条件。

当您抓取没有扩展名的文件时,这也将适用。为此目的使用的特定内置函数仅在找到的对象是文件的情况下评估天气,然后在文件名中是否包含点号。

如果您只读取目录而不包含太多文件,则节省的空间可能不大。但是,如果您正在读取大量目录,或者该目录中有成千上万个文件,那么可能会节省很多。

#include <stdio.h>
#include <sys/stat.h>
#include <iostream>
#include <dirent.h>
#include <map>

std::map<int, std::string> getFile(std::string p, std::string e = "", unsigned char s = '/'){
    if ( p.size() > 0 ){
        if (p.back() != s) p += s;
    }
    if ( e.size() > 0 ){
        if ( e.at(0) != '.' && !(e.size() == 1 && e.at(0) == '*') ) e = "." + e;
    }

    DIR *dir;
    struct dirent *ent;
    struct stat sb;
    std::map<int, std::string> r = {{999, "FAILED"}};
    std::string temp;
    int f = 0;
    bool fd;

    if ( (dir = opendir(p.c_str())) != NULL ){
        r.erase (999);
        while ((ent = readdir (dir)) != NULL){
            temp = ent->d_name;
            fd = temp.find(".") != std::string::npos? true : false;
            temp = p + temp;

            if (stat(temp.c_str(), &sb) == 0 && S_ISREG(sb.st_mode)){
                if ( e.size() == 1 && e.at(0) == '*' ){
                    r[f] = temp;
                    f++;
                } else {
                    if (e.size() == 0){
                        if ( fd == false ){
                            r[f] = temp;
                            f++;
                        }
                        continue;
                    }

                    if (e.size() > temp.size()) continue;

                    if ( temp.substr(temp.size() - e.size()) == e ){
                        r[f] = temp;
                        f++;
                    }
                }
            }
        }

        closedir(dir);
        return r;
    } else {
        return r;
    }
}

void printMap(auto &m){
    for (const auto &p : m) {
        std::cout << "m[" << p.first << "] = " << p.second << std::endl;
    }
}

int main(){
    std::map<int, std::string> k = getFile("./", "");
    printMap(k);
    return 0;
}

0
#include<iostream>
#include <dirent.h>
using namespace std;
char ROOT[]={'.'};

void listfiles(char* path){
    DIR * dirp = opendir(path);
    dirent * dp;
    while ( (dp = readdir(dirp)) !=NULL ) {
         cout << dp->d_name << " size " << dp->d_reclen<<std::endl;
    }
    (void)closedir(dirp);
}

int main(int argc, char **argv)
{
    char* path;
    if (argc>1) path=argv[1]; else path=ROOT;

    cout<<"list files in ["<<path<<"]"<<std::endl;
    listfiles(path);

    return 0;
}

-1

这对我有用。它仅使用所有文件的名称(无路径)写入文件。然后它将读取该txt文件并为您打印。

void DisplayFolderContent()
    {

        system("dir /n /b * > file_names.txt");
        char ch;
        std::fstream myStream("file_names.txt", std::fstream::in);
        while (myStream.get(ch))
        {
            std::cout << ch;
        }

    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.