你如何迭代通过标准C ++recursion的每个文件/目录?
你如何迭代通过标准C ++recursion的每个文件/目录?
在标准C ++中,从技术上讲,没有办法做到这一点,因为标准的C ++没有目录的概念。 如果你想扩展你的networking,你可能会喜欢使用Boost.FileSystem 。 这已经被TR2所接受,所以这给了你尽可能接近标准的最佳机会。
一个例子,从网站直接采取:
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; }
如果使用Win32 API,则可以使用FindFirstFile和FindNextFile函数。
http://msdn.microsoft.com/en-us/library/aa365200(VS.85).aspx
对于目录的recursion遍历,你必须检查每个WIN32_FIND_DATA.dwFileAttributes来检查FILE_ATTRIBUTE_DIRECTORY位是否被设置。 如果该位被设置,那么你可以recursion调用该目录的function。 或者,您可以使用堆栈来提供recursion调用的相同效果,但避免堆栈溢出很长的path树。
#include <windows.h> #include <string> #include <vector> #include <stack> #include <iostream> using namespace std; bool ListFiles(wstring path, wstring mask, vector<wstring>& files) { HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA ffd; wstring spec; stack<wstring> directories; directories.push(path); files.clear(); while (!directories.empty()) { path = directories.top(); spec = path + L"\\" + mask; directories.pop(); hFind = FindFirstFile(spec.c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { return false; } do { if (wcscmp(ffd.cFileName, L".") != 0 && wcscmp(ffd.cFileName, L"..") != 0) { if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { directories.push(path + L"\\" + ffd.cFileName); } else { files.push_back(path + L"\\" + ffd.cFileName); } } } while (FindNextFile(hFind, &ffd) != 0); if (GetLastError() != ERROR_NO_MORE_FILES) { FindClose(hFind); return false; } FindClose(hFind); hFind = INVALID_HANDLE_VALUE; } return true; } int main(int argc, char* argv[]) { vector<wstring> files; if (ListFiles(L"F:\\cvsrepos", L"*", files)) { for (vector<wstring>::iterator it = files.begin(); it != files.end(); ++it) { wcout << it->c_str() << endl; } } return 0; }
你可以使用基于和Boost的新的C ++ 11范围更简单:
#include <boost/filesystem.hpp> using namespace boost::filesystem; struct recursive_directory_range { typedef recursive_directory_iterator iterator; recursive_directory_range(path p) : p_(p) {} iterator begin() { return recursive_directory_iterator(p_); } iterator end() { return recursive_directory_iterator(); } path p_; }; for (auto it : recursive_directory_range(dir_path)) { std::cout << it << std::endl; }
一个快速的解决scheme是使用C的Dirent.h库。
从维基百科工作代码片段:
#include <stdio.h> #include <dirent.h> int listdir(const char *path) { struct dirent *entry; DIR *dp; dp = opendir(path); if (dp == NULL) { perror("opendir: Path does not exist or could not be read."); return -1; } while ((entry = readdir(dp))) puts(entry->d_name); closedir(dp); return 0; }
在带有“Filesystem TS”的C ++ 11/14中, <experimental/filesystem>
标题和范围可以简单地做到这一点:
#include <experimental/filesystem> using std::experimental::filesystem::recursive_directory_iterator; ... for (auto& dirEntry : recursive_directory_iterator(myPath)) cout << dirEntry << endl;
除了上面提到的boost :: filesystem之外,你可能还想检查一下wxWidgets :: wxDir和Qt :: QDir 。
wxWidgets和Qt都是开源的,跨平台的C ++框架。
wxDir
提供了使用Traverse()
或更简单的GetAllFiles()
函数recursion遍历文件的灵活方法。 你可以用GetFirst()
和GetNext()
函数来实现遍历(我假设Traverse()和GetAllFiles()是最终使用GetFirst()和GetNext()函数的包装器)。
QDir
提供对目录结构及其内容的访问。 用QDir遍历目录有几种方法。 您可以用QDirIterator :: Subdirectories标志实例化的QDirIterator遍历目录内容(包括子目录)。 另一种方法是使用QDir的GetEntryList()函数并实现recursion遍历。
这里是示例代码(从这里 #例8-5),展示了如何遍历所有子目录。
#include <qapplication.h> #include <qdir.h> #include <iostream> int main( int argc, char **argv ) { QApplication a( argc, argv ); QDir currentDir = QDir::current(); currentDir.setFilter( QDir::Dirs ); QStringList entries = currentDir.entryList(); for( QStringList::ConstIterator entry=entries.begin(); entry!=entries.end(); ++entry) { std::cout << *entry << std::endl; } return 0; }
你可能想检查boost.filesystem
http://www.boost.org/doc/libs/1_31_0/libs/filesystem/doc/index.htm
您可以使用ftw(3)
或nftw(3)
在POSIX系统上使用C或C ++来遍历文件系统层次结构。
Boost :: filesystem提供了recursive_directory_iterator,这对于这个任务来说非常方便:
#include "boost/filesystem.hpp" #include <iostream> boost::filesystem::recursive_directory_iterator end; for (it("./"); it != end; ++it) { std::cout << *it << std::endl; }
您需要为文件系统遍历调用特定于OS的函数,如open()
和readdir()
。 C标准没有指定任何文件系统相关的function。
你没有。 C ++标准没有目录的概念。 实现将string转换为文件句柄。 该string的内容以及映射到的内容取决于操作系统。 请记住,C ++可以用来编写该操作系统,所以它被用于一个级别,要求如何遍历一个目录尚未定义(因为你正在编写目录pipe理代码)。
看看你的操作系统API文档如何做到这一点。 如果你需要可移植的,你将不得不有一堆#ifdef s各种操作系统。
你可能是最好的升压或C + + 14的实验文件系统的东西。 如果您正在parsing一个内部目录(即,用于程序closures后存储数据的程序),则创build一个索引文件,该索引文件具有文件内容的索引。 顺便说一句,你将来可能需要使用boost,所以如果你没有安装它,请安装它! 其次,你可以使用一个条件编译:
#ifdef WINDOWS //define WINDOWS in your code to compile for windows
代码在https://stackoverflow.com/a/67336/7077165
#ifdef POSIX //unix, linux, etc. #include <stdio.h> #include <dirent.h> int listdir(const char *path) { struct dirent *entry; DIR *dp; dp = opendir(path); if (dp == NULL) { perror("opendir: Path does not exist or could not be read."); return -1; } while ((entry = readdir(dp))) puts(entry->d_name); closedir(dp); return 0; } #endif #ifdef WINDOWS #include <windows.h> #include <string> #include <vector> #include <stack> #include <iostream> using namespace std; bool ListFiles(wstring path, wstring mask, vector<wstring>& files) { HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA ffd; wstring spec; stack<wstring> directories; directories.push(path); files.clear(); while (!directories.empty()) { path = directories.top(); spec = path + L"\\" + mask; directories.pop(); hFind = FindFirstFile(spec.c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { return false; } do { if (wcscmp(ffd.cFileName, L".") != 0 && wcscmp(ffd.cFileName, L"..") != 0) { if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { directories.push(path + L"\\" + ffd.cFileName); } else { files.push_back(path + L"\\" + ffd.cFileName); } } } while (FindNextFile(hFind, &ffd) != 0); if (GetLastError() != ERROR_NO_MORE_FILES) { FindClose(hFind); return false; } FindClose(hFind); hFind = INVALID_HANDLE_VALUE; } return true; } #endif //so on and so forth.
你没有。 标准C ++不会暴露给目录的概念。 具体来说,它不给出任何方式列出目录中的所有文件。
一个可怕的黑客将是使用system()调用和parsing结果。 最合理的解决scheme是使用某种跨平台的库,如Qt甚至POSIX 。
如果您在Windows上,则可以将FindFirstFile与FindNextFile API一起使用。 您可以使用FindFileData.dwFileAttributes来检查给定的path是文件还是目录。 如果它是一个目录,则可以recursion地重复该algorithm。
在这里,我列出了一些列出Windows机器上所有文件的代码。