C++ 如何在标准C+;中递归地遍历每个文件/目录+;?
如何在标准C++中递归遍历每个文件/目录?< p>您需要调用OS特定的函数来进行文件系统遍历,如C++ 如何在标准C+;中递归地遍历每个文件/目录+;?,c++,filesystems,C++,Filesystems,如何在标准C++中递归遍历每个文件/目录?< p>您需要调用OS特定的函数来进行文件系统遍历,如>OPEN()/和 Read DILL()/。C标准没有指定任何文件系统相关的函数。标准C++中的< P>,技术上没有办法做到这一点,因为标准C++没有目录概念。如果你想扩大你的网络一点,你可能想看看使用。这已经被接受并包含在TR2中,因此这为您提供了使实现尽可能接近标准的最佳机会 一个直接取自网站的示例: bool find_file( const path & dir_path,
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;
}
你没有。标准C++不暴露目录的概念。具体来说,它没有提供任何方法来列出目录中的所有文件
一个可怕的黑客行为是使用system()调用并解析结果。最合理的解决方案是使用某种跨平台库,例如或甚至。如果使用Win32 API,您可以使用FindFirstFile和FindNextFile函数 对于目录的递归遍历,您必须检查每个WIN32\u FIND\u DATA.dwFileAttributes以检查是否设置了文件属性\u DIRECTORY位。如果设置了位,则可以使用该目录递归调用函数。或者,您可以使用堆栈提供与递归调用相同的效果,但避免很长路径树的堆栈溢出
#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;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
bool列表文件(wstring路径、wstring掩码、向量和文件){
句柄hFind=无效的句柄值;
WIN32_查找_数据ffd;
wstring规范;
堆栈目录;
目录。推送(路径);
clear()文件;
而(!directories.empty()){
path=directories.top();
spec=路径+L“\\”+掩码;
目录pop();
hFind=FindFirstFile(规范c_str(),&ffd);
if(hFind==无效的句柄值){
返回false;
}
做{
如果(wcscmp(ffd.cFileName,L“)!=0&&
wcscmp(ffd.cFileName,L.“.”!=0){
if(ffd.dwFileAttributes和文件属性目录){
目录.push(路径+L“\\”+ffd.cFileName);
}
否则{
文件。向后推(路径+L“\\”+ffd.cFileName);
}
}
}while(FindNextFile(hFind,&ffd)!=0);
如果(GetLastError()!=错误\u没有\u更多\u文件){
FindClose(hFind);
返回false;
}
FindClose(hFind);
hFind=无效的句柄值;
}
返回true;
}
int main(int argc,char*argv[])
{
矢量文件;
如果(列表文件(L“F:\\cvsrepos”,L“*”,文件)){
for(vector::iterator it=files.begin();
it!=files.end();
++(it){
wcout c_str()< C++标准没有目录的概念。它是由一个字符串转换成文件句柄的实现。该字符串的内容和它映射到的是OS相关的。请记住,C++可以用来编写操作系统,因此它在一个要求使用如何遍历目录的级别上还没有被定义。(因为您正在编写目录管理代码)
查看您的操作系统API文档了解如何做到这一点。如果您需要可移植,则必须为各种操作系统提供一系列的文件系统。除了上面提到的boost::filesystem之外,您可能还需要检查和安装这些文件系统
两个WXWIDGET和QT都是开源的跨平台C++框架。
wxDir
提供了一种使用traverse()
或更简单的GetAllFiles()
函数递归遍历文件的灵活方法。此外,您还可以使用GetFirst()
和GetNext()
函数实现遍历(我假设traverse()和GetAllFiles()是最终使用GetFirst()的包装器)和GetNext()函数)
QDir
提供对目录结构及其内容的访问。使用QDir遍历目录有几种方法。您可以使用QDirIterator::Subdirectories标志实例化的QDirIterator迭代目录内容(包括子目录)。另一种方法是使用QDir的GetEntryList()函数并实现递归遍历
下面是示例代码(取自#示例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;
}
#包括
#包括
#包括
int main(int argc,字符**argv)
{
质量保证申请a(argc、argv);
QDir currentDir=QDir::current();
currentDir.setFilter(QDir::Dirs);
QStringList entries=currentDir.entryList();
对于(QStringList::conditerator entry=entries.begin();entry!=entries.end();++entry)
{
一个快速的解决方案是使用C的库
维基百科的工作代码片段:
#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;
}
#包括
#包括
int listdir(常量字符*路径){
结构方向*条目;
DIR*dp;
dp=opendir(路径);
如果(dp==NULL){
perror(“opendir:Path不存在或无法读取”);
返回-1;
}
while((entry=readdir(dp)))
puts(输入->d_名称);
closedir(dp);
返回0;
}
使用新的基于范围的for
和:
#包括
使用名称空间boost::filesystem;
结构递归目录范围
{
typedef递归目录迭代器迭代器;
递归目录范围(路径p):p(p){}
迭代器begin(){return recursive_directory_iterator(p_u);}
迭代器end(){return recursive_directory_iterator();}
路径p_;
};
用于(自动it:递归目录范围(目录路径))
{
STD::CUT< P>可以在C或C++系统上使用文件系统层次结构。
#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;
}
#include "boost/filesystem.hpp"
#include <iostream>
using namespace boost::filesystem;
recursive_directory_iterator end;
for (recursive_directory_iterator it("./"); it != end; ++it) {
std::cout << *it << std::endl;
}
#include <filesystem>
using recursive_directory_iterator = std::filesystem::recursive_directory_iterator;
...
for (const auto& dirEntry : recursive_directory_iterator(myPath))
std::cout << dirEntry << std::endl;
#ifdef WINDOWS //define WINDOWS in your code to compile for windows
#endif
#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.
#include <iostream>
#include <string>
#include <filesystem>
void listFiles(std::string path)
{
for (auto& dirEntry: std::filesystem::recursive_directory_iterator(path)) {
if (!dirEntry.is_regular_file()) {
std::cout << "Directory: " << dirEntry.path() << std::endl;
continue;
}
std::filesystem::path file = dirEntry.path();
std::cout << "Filename: " << file.filename() << " extension: " << file.extension() << std::endl;
}
}
int main()
{
listFiles("./");
return 0;
}
size_t directory_size(const std::filesystem::path& directory)
{
size_t size{ 0 };
for (const auto& entry : std::filesystem::recursive_directory_iterator(directory))
{
if (entry.is_regular_file() && !entry.is_symlink())
{
size += entry.file_size();
}
}
return size;
}
#include <ftw.h>
#include <stdio.h>
#include <sys/stat.h>
#include <string.h>
int list(const char *name, const struct stat *status, int type)
{
if (type == FTW_NS)
{
return 0;
}
if (type == FTW_F)
{
printf("0%3o\t%s\n", status->st_mode&0777, name);
}
if (type == FTW_D && strcmp(".", name) != 0)
{
printf("0%3o\t%s/\n", status->st_mode&0777, name);
}
return 0;
}
int main(int argc, char *argv[])
{
if(argc == 1)
{
ftw(".", list, 1);
}
else
{
ftw(argv[1], list, 1);
}
return 0;
}
0755 ./Shivaji/
0644 ./Shivaji/20200516_204454.png
0644 ./Shivaji/20200527_160408.png
0644 ./Shivaji/20200527_160352.png
0644 ./Shivaji/20200520_174754.png
0644 ./Shivaji/20200520_180103.png
0755 ./Saif/
0644 ./Saif/Snapchat-1751229005.jpg
0644 ./Saif/Snapchat-1356123194.jpg
0644 ./Saif/Snapchat-613911286.jpg
0644 ./Saif/Snapchat-107742096.jpg
0755 ./Milind/
0644 ./Milind/IMG_1828.JPG
0644 ./Milind/IMG_1839.JPG
0644 ./Milind/IMG_1825.JPG
0644 ./Milind/IMG_1831.JPG
0644 ./Milind/IMG_1840.JPG
#include <ftw.h>
#include <stdio.h>
#include <sys/stat.h>
#include <iostream>
#include <fnmatch.h>
static const char *filters[] = {
"*.jpg", "*.jpeg", "*.png"
};
int list(const char *name, const struct stat *status, int type)
{
if (type == FTW_NS)
{
return 0;
}
if (type == FTW_F)
{
int i;
for (i = 0; i < sizeof(filters) / sizeof(filters[0]); i++) {
/* if the filename matches the filter, */
if (fnmatch(filters[i], name, FNM_CASEFOLD) == 0) {
printf("0%3o\t%s\n", status->st_mode&0777, name);
break;
}
}
}
if (type == FTW_D && strcmp(".", name) != 0)
{
//printf("0%3o\t%s/\n", status->st_mode&0777, name);
}
return 0;
}
int main(int argc, char *argv[])
{
if(argc == 1)
{
ftw(".", list, 1);
}
else
{
ftw(argv[1], list, 1);
}
return 0;
}
#include <filesystem>
#include <iostream>
#include <vector>
namespace fs = std::filesystem;
int main()
{
std::ios_base::sync_with_stdio(false);
for (const auto &entry : fs::recursive_directory_iterator(".")) {
if (entry.path().extension() == ".png") {
std::cout << entry.path().string() << std::endl;
}
}
return 0;
}
bool Parser::queryDIR(string dir_name) {
vector<string> sameLayerFiles;
bool ret = false;
string dir = "";
//employee wide char
dir = dir_name + "\\*.*";;
//employee WIN File API
WIN32_FIND_DATA fd;
WIN32_FIND_DATA fd_dir;
HANDLE hFind = ::FindFirstFile(getWC(dir.c_str()), &fd);
HANDLE hFind_dir = ::FindFirstFile(getWC(dir.c_str()), &fd_dir);
string str_subdir;
string str_tmp;
//recursive call for diving into sub-directories
do {
if ((fd_dir.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
//ignore trival file node
while(true) {
FindNextFile(hFind_dir, &fd_dir);
str_tmp = wc2str(fd_dir.cFileName);
if (str_tmp.compare(".") && str_tmp.compare("..")){
break;
}
}
if ((fd_dir.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
str_subdir = wc2str(fd_dir.cFileName);
ret = queryDIR(dir_name + "\\" + str_subdir);
}
}
} while(::FindNextFile(hFind_dir, &fd_dir));
//iterate same layer files
do {
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
str_tmp = wc2str(fd.cFileName);
string fname = dir_name + "\\" + str_tmp;
sameLayerFiles.push_back(fname);
}
} while(::FindNextFile(hFind, &fd));
for (std::vector<string>::iterator it=sameLayerFiles.begin(); it!=sameLayerFiles.end(); it++) {
std::cout << "iterated file:" << *it << "..." << std::endl;
//Doing something with every file here
}
return true;
}