c/c++遍历文件几种方式

c/c++遍历文件

一般使用opendir方式

1.使用ftw方法

ftw.h头文件不是标准c库,MSVC是没有该头文件的,需要mingw

int ftw(const char *dirpath, int (*fn)(const char *fpath, const struct stat *sb, int typeflag), int nopenfd);

dirpath: 要遍历的根目录的路径。
fn: 一个用户定义的回调函数,用于处理每个找到的文件和目录。这个函数会被调用多次,每次传递不同的文件或目录信息给它。
nopenfd: 指定同时打开的文件描述符的最大数目,通常可以设置为 0(0表示不限制同时打开的文件描述符的数量,函数将根据需要打开文件)。这个参数主要限制限制资源的使用,在速度和资源情况下设置

int nftw(const char *dirpath, int (*fn)(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf), int nopenfd, int flags);

dirpath: 要遍历的根目录的路径。
fn: 一个用户定义的回调函数,用于处理每个找到的文件和目录。这个函数会被调用多次,每次传递不同的文件或目录信息给它。
nopenfd: 指定同时打开的文件描述符的最大数目,通常可以设置为 0(0表示不限制同时打开的文件描述符的数量,函数将根据需要打开文件)。这个参数主要限制限制资源的使用,在速度和资源情况下设置
flags: 用于控制遍历行为的标志,比如是否要递归遍历子目录、是否要跟踪符号链接等。

结构体struct stat在#include <sys/stat.h>

struct stat {
    _dev_t st_dev; // 文件所在的设备的ID。
    _ino_t st_ino; //文件所有者的用户ID。
    unsigned short st_mode; //文件类型和访问权限。
    short st_nlink; //文件所有者的组ID。
    short st_uid; //文件所有者的用户ID。
    short st_gid; //表示文件或目录的所有者的组ID
	 //_dev_t 是一个用于表示设备ID的数据类型,它通常是一个整数类型。
	//对于普通文件和目录,st_rdev 的值通常是0,因为它不是一个特殊文件。
	//对于设备文件(如字符设备或块设备),st_rdev 用于标识关联的设备。
    _dev_t st_rdev; // 表示特殊文件(如设备文件)的设备ID
    _off_t st_size; //文件所有者的用户ID。
    time_t st_atime; //文件的最后访问时间。(秒级的时间戳)
    time_t st_mtime; //文件的最后修改时间。(秒级的时间戳)
    time_t st_ctime; //文件的最后状态改变时间(例如,权限变化)
  };
//stat 获取文件info
struct stat file_info;
stat(path, &file_info);

example1:

int process_file(const char* path, const struct stat* sb, int typeflag){
    if(typeflag == FTW_F){ //普通文件
        std::cout << "file:" << path << std::endl;
    }else if(typeflag == FTW_D){ //目录
        std::cout << "Directory:" << path << std::endl;
    }
    return 0;
}

int main(){
    const char *path = "./";
	
    int result = ftw(path,process_file, 0);
    if (result == -1) {
        std::cerr << "failed" << std::endl;
        return 1;
    }
    return 0;
}

限制递归层级
example2(只记录当前目录):

int process_file(const char* path, const struct stat* sb, int typeflag, struct FTW *ftwbuf){
    if (ftwbuf->level > 1) {
	// 如果目录深度大于0(即不在当前目录),
	// 返回FTW_SKIPSUB以停止递归
	// 返回FTW_CONTINUE继续
        return FTW_CONTINUE;
    }
    if (typeflag == FTW_F) {
        std::cout << "file:" << path << std::endl;
    } else if (typeflag == FTW_D) {
        std::cout << "Directory:" << path << std::endl;
    }
    return FTW_CONTINUE; // 返回0以继续遍历
}
void test_fwt(){
    const char *path = "./";
    int flags = FTW_PHYS;// 使用FTW_PHYS选项以跳过符号链接的解析
    int result = nftw(path, process_file, 0, flags);
    //resutl = -1 -> err
}

2. 使用opendir方法

opendir 标准C库函数(通用性好)
头文件dirent.h

遍历当前目录

void test_opendir(){
    const char* path = "./";

    DIR *dir = opendir(path);
    if(dir == nullptr){
    	std::cerr << "open dir failed." << std::endl;
    	return;
    }
    struct dirent* entry;

    while(((entry = readdir(dir)) != nullptr)){
        if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0){
            continue;
        }
        std::cout << "Name:" << entry->d_name << std::endl;
    }
    closedir(dir);
}

递归遍历子目录

void recursion_opendir(const char* path){
    DIR *dir = opendir(path);
    if(dir == nullptr){
    	std::cerr << "open dir failed." << std::endl;
    	return;
    }
    struct dirent* entry;

    while(((entry = readdir(dir)) != nullptr)){
        if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0){
            continue;
        }
        std::cout << "Name:" << entry->d_name << std::endl;
        char path1[1024];
        snprintf(path1, sizeof(path1), "%s/%s", path, entry->d_name);
        struct stat info;
        if (stat(path1, &info) == 0) {
            if (S_ISDIR(info.st_mode)) {
                std::cout << "Type: Directory" << std::endl;
                recursion_opendir(path1);
            } else if (S_ISREG(info.st_mode)) {
                std::cout << "Type: Regular File" << std::endl;
            }
        }
    }

    closedir(dir);
}

3.c++ 17提供的新filesystem头文件

void traverseDir(const std::filesystem::path& root, int depth = 0){
    try{
        if(std::filesystem::is_directory(root) && std::filesystem::exists(root)){
            for(const auto& entry:std::filesystem::directory_iterator(root)){
                for(int i = 0; i< depth; i++){
                    std::cout << " ";
                }
                std::cout << entry.path().filename() << std::endl;

                if(std::filesystem::is_directory(entry)){
                    traverseDir(entry, depth+1); // 递归遍历子目录
                }
            }
        }else{
            std::cout << "root is not directory or exists " << std::endl;
        }
    }catch(const std::exception &ex){
        std::cerr << "exception:" << ex.what() << std::endl;
    }
}

void test_filesystem(){
    std::filesystem::path root("./");
    traverseDir(root);
}

4 . Windows api 方式遍历目录

没有必要写啦

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要求文件中的图片数量,可以使用C++的OpenCV库,采用以下步骤: 1. 读取文件夹中的所有文件; 2. 遍历所有文件,通过文件的扩展名来确定是否为图片文件; 3. 如果是图片文件,则计数器加1。 以下是示例代码: ```cpp #include <iostream> #include <fstream> #include <string> #include <filesystem> #include <opencv2/opencv.hpp> using namespace std; int main() { string folder_path = "C:\\example_folder"; // 文件夹路径 int img_count = 0; // 图片计数器 for (const auto & entry : filesystem::directory_iterator(folder_path)) { if (entry.is_regular_file()) // 如果是文件 { string file_path = entry.path().string(); // 获取文件的完整路径 string file_ext = file_path.substr(file_path.find_last_of(".") + 1); // 获取文件扩展名 if (file_ext == "jpg" || file_ext == "jpeg" || file_ext == "png" || file_ext == "bmp") // 如果是图片文件 { cv::Mat img = cv::imread(file_path); // 读取图片 if (!img.empty()) // 如果图片读取成功 { img_count++; // 计数器加1 } } } } cout << "The number of images in the folder is: " << img_count << endl; return 0; } ``` 上述代码使用了OpenCV库中的cv::imread()函数来读取图片文件,并判断图片读取是否成功。如果成功,则计数器加1。最后输出计数器的值即可得到文件夹中的图片数量。注意,这里只考虑了常见的几种图片格式,如果需要支持更多格式,可以根据需要进行扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值