一个查找文件的类:它的长处在于能够搜索子目录并且是可控制的

2023-05-16

// find_file.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
测试需要的头文件
#include <conio.h>
#include <iostream>
//

x_find_file类需要的头文件

#include <windows.h>
#include <sys/stat.h>
#include <string>
#include <list>
using namespace std;
//
功能:
在指定目录及其子目录查找文件,封装了WIN32的API。
查找结果按文件创建时间排列顺序
作者:陈立福(AARON)
class x_find_file
{
private:

 WIN32_FIND_DATA find_data;
 HANDLE find_handle;
 bool find_sub;      是否查找子目录
 bool find_extent;     是否广度查找优先
 bool dir_changed;     是否改变了当前查找目录
 char separator;      文件目录分隔符,windows文件系统是'//'
 string origin_dir;     原始目录
 string current_dir;     当前查找的目录
 string find_filename;    查找的文件,可含通配符
 string find_result;     最后一次查找的结果,不含路径
 list < string > find_dirs;   待查找的目录队列
public:
 x_find_file()
 {
  find_sub = false;       默认不搜索子目录
  find_extent = true;       默认广度搜索优先
  dir_changed = false;
  separator = '//';       文件目录分隔符,windows文件系统是'//'
  find_handle = INVALID_HANDLE_VALUE;
 }
 
 ~x_find_file()
 {
  if( find_handle != INVALID_HANDLE_VALUE )
  {
   ::FindClose( find_handle );
   find_handle = INVALID_HANDLE_VALUE;
  }
 }
 
private:
  不可以复制对象
 x_find_file( const x_find_file & );
 operator = ( const x_find_file & );
public:
 
  功能:
  读取指定目录下的子目录,不在它的子目录中继续执行查找
  输入:
  [dir]:执行查找的目录
  [separator]:目录分隔符,默认为windows下的'//'
  输出:
  [sub_sirs]:查找到的子目录列表,按找到的先后顺序加入列表后面
  列表原有数据不会被改变,如果查找失败(没有子目录),列表不会被改变
  每个子目录项都包含[dir]
  返回值:
  找到子目录返回true,否则返回false
  该函数被声明为static
 static bool pick_sub_dirs( const string & dir, list < string > & sub_sirs,
        char separator =  '//' )
 {
  if ( dir.size() < 1 )
  {
   return false;
  }
  
  char directory[ 2 * MAX_PATH ];
  strcpy( directory, dir.c_str() );
  int dir_len = strlen( directory );
  if( directory[ dir_len - 1 ] != separator )
  {
   directory[ dir_len ] = separator;
   directory[ dir_len + 1 ] = '/0';
  }
  
    
  char find_string[ 2 * MAX_PATH ];
  strcpy( find_string , directory );
  strcat( find_string, "*.*" );
  
  WIN32_FIND_DATA find_sub_data;
  HANDLE find_sub_handle;
  
  find_sub_handle = ::FindFirstFile( find_string, &find_sub_data);
  if ( find_sub_handle == INVALID_HANDLE_VALUE )
  {
   return false;
  }
  
  do
  {
   if ( strcmp( find_sub_data.cFileName, "." )
    && strcmp( find_sub_data.cFileName, ".." ) )
   {
    char filename[ 2 * MAX_PATH ];
    strcpy( filename, directory );
    strcat( filename, find_sub_data.cFileName );
    struct stat fileinfo;
    if ( stat( filename, &fileinfo ) == 0 )
    {
     if ( fileinfo.st_mode & S_IFDIR )
     {      
      sub_sirs.push_back( filename );
     }
    }
   }
  }
  while( ::FindNextFile( find_sub_handle, &find_sub_data ) );
  
  ::FindClose( find_sub_handle );
  
  return ( sub_sirs.size() > 0 );
  
 }
protected:
  到下一目录查找第一个文件
  并改变当前查找目录为该目录
  只要还有下一个目录可以继续查找
  就一直执行查找
  直到找到第一个文件并返回true为止
  否则返回false
  表示没有更多的目录可以继续查找
 bool find_in_next_dir()
 {
  while ( find_dirs.size() > 0 )
  {
    更改当前查找目录为待查找目录列表的第一个目录
    并将该目录移出待查找目录列表
   current_dir = find_dirs.front();
   find_dirs.pop_front();
   dir_changed = true;
   if ( find_first_file() )
   {
    return true;
   }
  }
  
  return false;  
 }
public:
 
  设置原始目录以及第一个查找的目录
 void set_origin_dir( const string & dir )
 {
  origin_dir = dir;
  current_dir = dir;
 }
  读取原始目录名
 string get_origin_dir() const
 {
  return origin_dir;
 }
 
  设置并读取目录分隔符
 void set_separator( char ch )
 {
   windows文件系统的目录分隔符是'//'
   separator = ch;
 }
  返回类内部使用的目录分隔符
  是为了在使用该类对象查找到一个文件全路径名之后
  如果想分析该文件名的路径时能够使用与类内相同的目录分隔符
  而不是显式的使用'//'
 char get_separator() const
 {
  return separator;
 }
  设置要查找的文件名,可以包含通配符,也可以包含路径名
  如果包含路径名,那么该路径是从set_origin_dir函数设定的路径开始
 void set_find_filename( const string & filename )
 {
  find_filename = filename;
 }
  读取要查找的文件名
 string get_find_filename() const
 {
  return find_filename;
 }
  设置及读取是否查找子目录
 void set_find_sub( bool find )
 {
  find_sub = find;
 }
 bool is_find_sub() const
 {
  return find_sub;
 }
  设置及读取是否广度查找优先
 void set_find_extent( bool extent )
 {
  find_extent = extent;
 }
 bool is_find_extent() const
 {
  return find_extent;
 }
  检测是否切换了当前查找目录
 bool is_dir_changed() const
 {
  return dir_changed;
 }
  读取最后一次查找的文件名,不含路径
 string get_filename() const
 {
  return find_result;
 }
 
  读取最后一次查找的文件名
  包含从set_origin_dir函数设定的路径开始的路径
 string get_path_filename() const
 {
  char filename[ 2 * MAX_PATH ];
  strcpy( filename, current_dir.c_str() );
  int dir_len = strlen( filename );
  if ( dir_len > 0 )
  {
   if ( filename[ dir_len - 1 ] != separator )
   {
    filename[ dir_len ] = separator;
    filename[ dir_len + 1 ] = '/0';
   }
  }
  strcat( filename, find_result.c_str() );
  return filename;
 }
 
  读取当前执行查找的目录
  包含从set_origin_dir函数设定的路径开始的路径
 string get_current_dir() const
 {
  return current_dir;
 }
  在当前目录中查找第一个文件
  如果找到第一个文件就返回true
  否则如果还有更多的目录可以继续查找(查找子目录)
  就继续在下一目录中执行查找
  一直到找到第一个文件或者没有更多的目录可以继续查找为止
  如果找到第一个文件则返回true
  否则返回false
  执行查找时,该函数应该首先被调用并且只调用一次
  否则将得不到正确的查找结果
 bool find_first_file()
 {
  if ( current_dir.size() < 1 )
  {
   return false;
  }
  if ( find_filename.size() < 1 )
  {
   return false;
  }
  
  if ( find_sub )
  {
    如果在子目录中执行查找
    则将当前目录的子目录读出并根据广度优先还是深度优先
    将这些子目录相应的插入到待查找目录列表的尾部或者头部
    他们在列表中的顺序就是他们被执行查找的顺序
    在当前目录查找第一个文件的时候,它的子目录才被读出
   list < string > sub_dirs;
   if ( pick_sub_dirs( current_dir, sub_dirs, separator ) )
   {
    if ( find_extent )
    {
     find_dirs.insert( find_dirs.end(), sub_dirs.begin(), sub_dirs.end() );
    }
    else
    {
     find_dirs.insert( find_dirs.begin(), sub_dirs.begin(), sub_dirs.end() );
    }
   }
  }
  //
  
  char directory[ 2 * MAX_PATH ];
  strcpy( directory, current_dir.c_str() );
  int dir_len = strlen( directory );
  if( directory[ dir_len - 1 ] != separator )
  {
   directory[ dir_len ] = separator;
   directory[ dir_len + 1 ] = '/0';
  }
  
  
  char find_string[ 2 * MAX_PATH ];
  strcpy( find_string , directory );
  strcat( find_string, find_filename.c_str() );
  
   这种情况不应该出现的
   if ( find_handle != INVALID_HANDLE_VALUE )
   {
    ::FindClose( find_handle );
    find_handle = INVALID_HANDLE_VALUE;
   }
  
  find_handle = ::FindFirstFile( find_string, &find_data );
  if ( find_handle != INVALID_HANDLE_VALUE )
  {
   find_result = find_data.cFileName;
   return true;
  }
  
   在当前目录查找失败,到下一目录继续查找
   在这里有一个间接递归调用find_first_file
  return find_in_next_dir();
 }
  在当前目录查找下一个文件
  如果找则返回true
  否则如果还有更多的目录可以继续查找(查找子目录)
  就继续在下一目录中执行查找
  一直到找到第一个文件或者没有更多的目录可以继续查找为止
  如果找到第一个文件则返回true
  否则返回false
 bool find_next_file()
 {
  dir_changed = false;
  if ( find_handle != INVALID_HANDLE_VALUE )
  {
   if ( ::FindNextFile( find_handle, &find_data ) )
   {
    find_result = find_data.cFileName;
    return true;
   }
   ::FindClose( find_handle );
   find_handle = INVALID_HANDLE_VALUE;
  }
   在当前目录查找结束,则到下一目录查找
  return find_in_next_dir();
 }
 
};
//
int main(int argc, char* argv[])
{
  测试
 x_find_file finder;
 
  不可以复制对象
  x_find_file f1( finder );
  x_find_file f2 = finder;
  x_find_file f3; f3 = finder;
 finder.set_origin_dir( "C://" );
 finder.set_find_filename( "*.*" );
 finder.set_find_sub( true );
  finder.set_find_extent( false );
 
 if ( finder.find_first_file() ) find_first_file被调用且只调用一次
 {
  cout << "/ncurrent_directory:/n" << finder.get_current_dir() << endl;
  
  do
  {
   if ( finder.is_dir_changed() )
   {
    cout << "/npress 'q' to quit, else to continue..." << endl;
    if ( getch() == 'q' )
    {
     break;
    }
    cout << "/ncurrent_directory:/n" << finder.get_current_dir() << endl;
   }
    cout << finder.get_filename() << endl;
   cout << finder.get_path_filename() << endl;
  }
  while( finder.find_next_file() );
 }
 return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一个查找文件的类:它的长处在于能够搜索子目录并且是可控制的 的相关文章

  • linux安装go环境并配置国内源

    linux安装go环境并配置国内源 第一步 官网下载安装包 https golang google cn go1 4 linux amd64 tar gz 第二步 解压缩 tar C usr local xzf go1 4 linux am
  • python - 获取时间戳(10位和13位)

    在python 开发web程序时 xff0c 需要调用第三方的相关接口 xff0c 在调用时 xff0c 需要对请求进行签名 需要用到unix时间戳 在python里 xff0c 在网上介绍的很多方法 xff0c 得到的时间戳是10位 而j
  • curl命令模拟post请求发送json格式数据

    以下代码可以作为测试接收请求的程序直接复制使用 xff1a from flask import Flask request app 61 Flask name 64 app route 39 service 39 methods 61 39
  • pip换源 -pip更换国内镜像源

    更换pip源到国内镜像 pip国内的一些镜像 阿里云 http mirrors aliyun com pypi simple 中国科技大学 https pypi mirrors ustc edu cn simple 豆瓣 douban ht
  • 使用python的requests 发送multipart/form-data 请求

    发送post请求 1 r 61 requests post 34 http pythontab com postTest 34 data 61 34 key 34 34 value 34 以上得知 xff0c post请求参数是以data关
  • SHELL - shell 脚本获取本机ip并将ip复制给变量待用

    bin bash VAR 61 34 eth0 34 HOST IP 61 ifconfig VAR grep 34 inet addr 34 awk 39 print 2 39 awk F 39 print 2 39 echo HOST
  • shell - sed匹配某一行开头,替换整行内容

    sed i 39 cloud server ip ccloud server ip 61 update skyeye 360safe com 39 name txt
  • caffe安装系列——安装cuda和cudnn

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 说明 网上关于caffe的安装教程非常多 xff0c 但是关于每一步是否操作成功 xff0c 出现了什么样的错误又该如何处理没
  • caffe安装系列——安装OpenCV

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 说明 网上关于caffe的安装教程非常多 xff0c 但是关于每一步是否操作成功 xff0c 出现了什么样的错误又该如何处理没
  • 写递归函数的正确思维方法

    什么是递归 简单的定义 当函数直接或者间接调用自己时 xff0c 则发生了递归 说起来简单 但是理解起来复杂 因为递归并不直观 也不符合我们的思维习惯 相对于递归 我们更加容易理解迭代 因为我们日常生活中的思维方式就是一步接一步的 并且能够
  • PCL系列——拼接两个点云

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • PCL系列——三维重构之移动立方体算法

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • 字节(Byte)与位(bit)、十进制与二进制的关系

    一 基本常识 数据存储是以 字节 xff08 Byte xff09 为单位 xff0c 数据传输大多是以 位 xff08 bit xff0c 又名 比特 xff09 为单位 xff0c 一个位就代表一个0或1 xff08 即二进制 xff0
  • ubuntu20.04配置TensorFlow-GPU版本+对应版本的cuda&cudnn

    ubuntu20 04配置TensorFlow GPU版本 43 对应版本的cuda amp cudnn 配置说明 操作系统是Ubuntu20 04 xff0c GPU是NVIDIA GeForce RTX 2080 Ti xff0c Py
  • 十四、Rust ORM 框架

    Rust 下的 orm xff0c 之前笔者介绍过 sqlx xff0c 但使用中发现 sqlx 在进行参数绑定时 xff0c 使用的是 宏 xff0c 在当前的 IDE 生态环境下 xff0c 有时不能很好的进行代码提示 xff0c 或代
  • mybatis源码之集成mybatis-plus源码

    本文将结合源码介绍mybatis plus的原理 xff0c 包括 xff1a BaseMapper APIMybatisSqlSessionFactoryBean类BaseMapper API Statement解析Wrapper查询构建
  • Jpa 插入更新如何过滤null值

    使用Jpa时 xff0c 默认的save方法会将entity中null的值也更新到数据库 xff0c 这对与存在默认值或者更新接口将直接导致错误的记录产生 xff0c 那么如何解决这个问题 xff1f Hibernate提供了两个注解 64
  • 一个奇怪的java.lang.IncompatibleClassChangeError异常

    解决方法就是替换jdk版本 xff0c 下面都是废话 最近项目进行了一次小更新 xff0c 添加了一个很小很小的功能 xff0c 结果运行一段时间后莫名出现java lang IncompatibleClassChangeError xff
  • nginx的proxy_pass最后反斜杠/的问题

    如果只是host xff0c 如http host 带 xff1a 用代理的内容替换掉匹配的路径 不带 xff1a 拼接上匹配的路径 2 xff1a 如果是子路径 xff0c 如http host func 带和不带 xff1a 用代理的内
  • gitlab修改克隆地址

    1 修改gitlab yml文件 xff0c 修改gitlab下的host和port vi opt gitlab embedded service gitlab rails config gitlab yml 修改完成后执行gitlab c

随机推荐