zoukankan      html  css  js  c++  java
  • C++下遍历文件夹

    编写程序遍历文件夹及其子文件夹下所有文件,并输出到标准输出流或者文件流。

    1. 先考虑在单层目录下,遍历所有文件。以C:WINDOWS为例:

    用到数据结构_finddata_t,文件信息结构体的指针。

    复制代码
    struct _finddata_t
    {
    unsigned attrib; //文件属性
    time_t time_create; //文件创建时间
    time_t time_access; //文件上一次访问时间
    time_t time_write; //文件上一次修改时间
    _fsize_t size; //文件字节数
    char name[_MAX_FNAME]; //文件名
    };
    复制代码

    文件属性是无符号整数,取值为相应的宏:_A_ARCH(存档),_A_SUBDIR(文件夹),_A_HIDDEN(隐藏),_A_SYSTEM(系统),_A_NORMAL(正常),_A_RDONLY(只读)。容易看出,通过这个结构体,我们可以得到关于该文件的很多信息。结合以下函数,我们可以将文件信息存储到这个结构体中:

    //按FileName命名规则匹配当前目录第一个文件
    _findfirst(_In_ const char * FileName, _Out_ struct _finddata64i32_t * _FindData);
    //按FileName命名规则匹配当前目录下一个文件
    _findnext(_In_ intptr_t _FindHandle, _Out_ struct _finddata64i32_t * _FindData);
    //关闭_findfirst返回的文件句柄
    _findclose(_In_ intptr_t _FindHandle);

    _findfirst 函数返回的是匹配到文件的句柄,数据类型为long。遍历过程可以指定文件类型,这通过FileName的赋值来实现,例如要遍历C:WINDOWS下的所有.exe文件


    bool transfer(string fileName = "C:\Windows\*.exe", int exeNum = 0)
    {
    _finddata_t fileInfo;
    long handle = _findfirst(fileName.c_str(), &fileInfo);

    if (handle == -1L)
    {
    cerr << "failed to transfer files" << endl;
    return false;
    }

    do
    {
    exeNum ++;
    cout << fileInfo.name <<endl;
    } while (_findnext(handle, &fileInfo) == 0);
    cout << " .exe files' number: " << exeNum << endl;

    return true;
    }

    复制代码
    bool transfer(string fileName = "C:\Windows\*.exe", int exeNum = 0)
    {
    _finddata_t fileInfo;
    long handle = _findfirst(fileName.c_str(), &fileInfo);

    if (handle == -1L)
    {
    cerr << "failed to transfer files" << endl;
    return false;
    }

    do
    {
    exeNum ++;
    cout << fileInfo.name <<endl;
    } while (_findnext(handle, &fileInfo) == 0);
    cout << " .exe files' number: " << exeNum << endl;

    return true;
    }
    复制代码

     2. 遍历文件夹及其子文件夹下所有文件。操作系统中文件夹目录是树状结构,使用深度搜索策略遍历所有文件。用到_A_SUBDIR属性,可运行程序如下:

    void dfsFolder(string folderPath, ofstream &fout)
    {
    _finddata_t FileInfo;
    string strfind = folderPath + "\*";
    long Handle = _findfirst(strfind.c_str(), &FileInfo);

    if (Handle == -1L)
    {
    cerr << "can not match the folder path" << endl;
    exit(-1);
    }
    do{
    //判断是否有子目录
    if (FileInfo.attrib & _A_SUBDIR)
    {
    //这个语句很重要
    if( (strcmp(FileInfo.name,".") != 0 ) &&(strcmp(FileInfo.name,"..") != 0))
    {
    string newPath = folderPath + "\" + FileInfo.name;
    dfsFolder(newPath, fout);
    }
    }
    else
    {
    fout << folderPath << "\" << FileInfo.name << " ";
    }
    }while (_findnext(Handle, &FileInfo) == 0);

    _findclose(Handle);
    fout.close();
    }


    复制代码
    void dfsFolder(string folderPath, ofstream &fout)
    {
    _finddata_t FileInfo;
    string strfind = folderPath + "\*";
    long Handle = _findfirst(strfind.c_str(), &FileInfo);

    if (Handle == -1L)
    {
    cerr << "can not match the folder path" << endl;
    exit(-1);
    }
    do{
    //判断是否有子目录
    if (FileInfo.attrib & _A_SUBDIR)
    {
    //这个语句很重要
    if( (strcmp(FileInfo.name,".") != 0 ) &&(strcmp(FileInfo.name,"..") != 0))
    {
    string newPath = folderPath + "\" + FileInfo.name;
    dfsFolder(newPath, fout);
    }
    }
    else
    {
    fout << folderPath << "\" << FileInfo.name << " ";
    }
    }while (_findnext(Handle, &FileInfo) == 0);

    _findclose(Handle);
    fout.close();
    }
    复制代码

     在判断有无子目录的if分支中,由于系统在进入一个子目录时,匹配到的头两个文件(夹)是"."(当前目录),".."(上一层目录)。需要忽略掉这两种情况。当需要对遍历到的文件做处理时,在else分支中添加相应的代码就好

  • 相关阅读:
    为什么 PCB 生产时推荐出 Gerber 给工厂?
    Fedora Redhat Centos 有什么区别和关系?
    【KiCad】 如何给元件给元件的管脚加上划线?
    MCU ADC 进入 PD 模式后出现错误的值?
    FastAdmin 生产环境升级注意
    EMC EMI 自行评估记录
    如何让你的 KiCad 在缩放时不眩晕?
    KiCad 5.1.0 正式版终于发布
    一次单片机 SFR 页引发的“事故”
    java基础之集合
  • 原文地址:https://www.cnblogs.com/byteHuang/p/9534836.html
Copyright © 2011-2022 走看看