本文可转载,转载请注明出处:http://www.cnblogs.com/collectionne/p/6815924.html

前面的一篇文章我们讲了用Windows API遍历一个目录下的所有文件,这次我们讲用一种Windows/Linux通用的方法遍历一个目录下的所有文件。

Windows/Linux的IDE都会提供一个头文件——<io.h>。看名字,似乎是关于I/O的,但是实际上它还提供了类似于WIN32_FIND_DATA、FindFirstFile()、FindNextFile()和FindClose()的查找文件的功能。

_finddata_t结构

_finddata_t结构用来记录查找到的文件的信息。实际上有_finddata32_t、_finddata32i64_t、_finddata64i32_t、_finddata64_t、_wfinddata32_t、_wfinddata32i64_t、_wfinddata64i32_t、_wfinddata64_t八个结构,但都只是在32位/64位整数和字符类型上有所区别,但整体上相同。大致定义如下(MSDN):

struct _finddata_t
{
unsigned attrib;
size_t time_create;
size_t time_access;
size_t time_write;
_fsize_t size;
char name[_MAX_PATH];
};

对于不同的_finddata_t结构,time_create、time_access和time_write的类型为_time32_t或_time64_t,size的类型为_fsize_t或__int64,name为char[_MAX_PATH]或wchar_t[_MAX_PATH]。

attrib

unsigned类型,文件属性。

time_create

_time32_t/_time64_t类型,文件创建时间(FAT文件系统为-1)。以UTC格式存储,如果需要转换成当地时间,使用localtime_s()。

time_access

_time32_t/_time64_t类型,文件最后一次被访问的时间(FAT文件系统为-1)。以UTC格式存储,如果需要转换成当地时间,使用localtime_s()。

time_write

_time32_t/_time64_t类型,文件最后一次被写入的时间。以UTC格式存储,如果需要转换成当地时间,使用localtime_s()。

size

_fsize_t/__int64类型,文件的长度(以字节为单位)。

name

char[_MAX_PATH]/wchar_t[_MAX_PATH]类型,文件/目录名,不包含路径。

对于不支持文件创建时间、文件上一次访问时间的文件系统,time_create和time_access为-1。

_MAX_PATH在stdlib.h中被定义为260。

一般_finddata_t被定义为_finddata32_t/_finddata64i32_t,_wfinddata_t被定义为_wfinddata32_t/_wfinddata64i32_t。为方便,下文中将_finddata_t和_wfinddata_t统称为_finddata_t。

文件属性常量

一个文件/目录可以有多种属性,每种属性可以是下面列出的属性之一。

_A_ARCH

档案。文件被BACKUP指令改变或清除时被设置。值:0x20。

_A_HIDDEN

隐藏。使用DIR指令一般看不到,除非使用/AH选项。值:0x02。

_A_NORMAL

普通。文件没有更多属性被设置,可以没有限制地被读或写。值:0x00。

_A_RDONLY

只读。不能以“写”为目的打开该文件,并且不能创建同名的文件。值:0x01。

_A_SUBDIR

子目录。值:0x10。

_A_SYSTEM

系统文件。使用DIR指令一般看不见,除非使用/A或/A:S选项。值:0x04。

要检查x是否含有某个属性a,可以用x & a进行检查。指定多个属性可以使用按位or运算符,例如_A_SYSTEM |  _A_RDONLY | _A_HIDDEN。

通配符(wildcards)

遍历文件目录时需要使用通配符,详见我的另一篇文章

_findfirst()/_findnext()/_findclose()函数

_findfirst()函数

intptr_t _findfirst(
const char * filespec,
struct _finddata_t *fileinfo
);

实际上_findfirst()有10个版本,这里只列出一个。

filespec

const char */const wchar_t *类型,目标文件说明(可包含通配符)。

fileinfo

_finddata_t *类型,函数将会填入文件/目录信息。

返回值

如果成功,返回一个唯一的搜索句柄标识一个或一组和filespec说明匹配的文件,可以用于接下来的_findnext()和_findclose()函数。否则_findfirst()返回-1。注意,intptr_t并不是指针类型,只是int或__int64的typedef。

_findnext()函数

int _findnext(
intptr_t handle,
struct _finddata_t *fileinfo
);

handle

intptr_t类型,搜索句柄。

fileinfo

_finddata_t *类型,函数将会填入文件/目录信息。

返回值

如果成功,返回0,否则返回-1。如果没有更多能够找到的文件了,也会导致失败。

_findclose()函数

int _findclose(
intptr_t handle
);

关闭搜索句柄并释放相应的资源。

handle

搜索句柄。

返回值

成功返回0,失败返回-1。

程序代码

1. 遍历目录下的所有文件

#include <iostream>
#include <cstring> // for strcat()
#include <io.h>
using namespace std; void listFiles(const char * dir); int main()
{
char dir[];
cout << "Enter a directory (ends with \'\\\'): ";
cin.getline(dir, ); strcat(dir, "*.*"); // 在要遍历的目录后加上通配符
listFiles(dir); return ;
} void listFiles(const char * dir)
{
intptr_t handle;
_finddata_t findData; handle = _findfirst(dir, &findData); // 查找目录中的第一个文件
if (handle == -)
{
cout << "Failed to find first file!\n";
return;
} do
{
if (findData.attrib & _A_SUBDIR
&& strcmp(findData.name, ".") ==
&& strcmp(findData.name, "..") ==
) // 是否是子目录并且不为"."或".."
cout << findData.name << "\t<dir>\n";
else
cout << findData.name << "\t" << findData.size << endl;
} while (_findnext(handle, &findData) == ); // 查找目录中的下一个文件 cout << "Done!\n";
_findclose(handle); // 关闭搜索句柄
}

程序遍历目录下的所有文件/目录,如果是文件则输出文件大小。

注意_findnext()函数成功返回0,因此要加上==0或!=-1进行判断,不能省略。

此外还有一个值得注意的地方:

if (findData.attrib & _A_SUBDIR
&& strcmp(findData.name, ".")
&& strcmp(findData.name, "..")
)
...

使用_findfirst()、_findnext()进行搜索时,可能会得到"."和".."两个文件夹名。这两个值可以忽略。

2. 遍历目录中的所有文件

注意是“目录中”而不是“目录下”,这个程序将会遍历一个目录里包含的所有文件。

#include <iostream>
#include <cstring> // for strcpy(), strcat()
#include <io.h> using namespace std; void listFiles(const char * dir); int main()
{
char dir[];
cout << "Enter a directory: ";
cin.getline(dir, ); listFiles(dir); return ;
} void listFiles(const char * dir)
{
char dirNew[];
strcpy(dirNew, dir);
strcat(dirNew, "\\*.*"); // 在目录后面加上"\\*.*"进行第一次搜索 intptr_t handle;
_finddata_t findData; handle = _findfirst(dirNew, &findData);
if (handle == -) // 检查是否成功
return; do
{
if (findData.attrib & _A_SUBDIR)
{
if (strcmp(findData.name, ".") == || strcmp(findData.name, "..") == )
continue; cout << findData.name << "\t<dir>\n"; // 在目录后面加上"\\"和搜索到的目录名进行下一次搜索
strcpy(dirNew, dir);
strcat(dirNew, "\\");
strcat(dirNew, findData.name); listFiles(dirNew);
}
else
cout << findData.name << "\t" << findData.size << " bytes.\n";
} while (_findnext(handle, &findData) == ); _findclose(handle); // 关闭搜索句柄
}

C/C++遍历目录下的所有文件(Windows/Linux篇,超详细)的更多相关文章

  1. C/C++遍历目录下的所有文件(Windows篇,超详细)

    注: 1. 本文讨论的是怎么用Windows API遍历目录下的所有文件.除Windows API,还有一种Windows/Linux通用的方式,使用<io.h>. 2. 本文部分翻译自M ...

  2. windows 遍历目录下的所有文件 FindFirstFile FindNextFile

    Windows下遍历文件时用到的就是FindFirstFile 和FindNextFile 首先看一下定义: HANDLE FindFirstFile( LPCTSTR lpFileName, // ...

  3. C 给定路径遍历目录下的所有文件

    在此之前需要了解 WIN32_FIND_DATA的结构 以及  FindFirstFile. FindNextFile原型以及用法注意事项传送门如下 https://msdn.microsoft.co ...

  4. php 遍历目录下的所以文件和文件夹

    <?php/** * 遍历文件夹和文件列 * @author lizhiming * @date 2016/06/30 */define('DS', DIRECTORY_SEPARATOR); ...

  5. 遍历目录下的所有文件-os.walk

    #coding:utf-8 import os for root,dirs,files in os.walk("D:"): for fileItem in files: print ...

  6. shell 遍历目录下的所有文件

    dir=/usr/local/nginx/logs for file in $dir/*; do echo $file done //结果 ./test.sh /usr/local/nginx/log ...

  7. shell编程--遍历目录下的文件

    假定目录text下有如下文件      目录:dir_1.dir_2.dir_3 文件:text_1.text_2 遍历目录下所有的文件是目录还是文件 if -- if类型: #!bin/sh for ...

  8. C++遍历路径下的所有文件

    intptr_t类型用于记录文件夹句柄,注意该类型不是指针类型,而是int型的重定义. _finddata_t结构体类型用于记录文件信息. _finddata_t结构体定义如下 struct _fin ...

  9. 复制D:\\day05目录下的所有文件到D:\\copy,并将.txt文件改为.java文件。

    **解题思路: 1.首先定义一个静态的refile方法,参数传入两个文件路径 2.要复制目录下的所有文件,首先查询File类的方法,可以使用listFiles方法得到目录下的文件 3.想到这问题基本就 ...

随机推荐

  1. Asp .Net MVC4笔记之走进MVC

    一.MVC三层架构: mvc三层架构,大家都比较熟悉了,这里再介绍一下.Mvc将应用程序分离为三个部分: Model:是一组类,用来描述被处理的数据,同时也定义这些数据如何被变更和操作的业务规则.与数 ...

  2. OC 常见面试题以及答案

    一. #improt 和include区别?@class? 1.include 主要用用来引用C 文件  import 主要引用OC 头文件  import 确保一个文件只能被导入一次  避免了交叉编 ...

  3. 【 js 模块加载 】深入学习模块化加载(node.js 模块源码)

    一.模块规范 说到模块化加载,就不得先说一说模块规范.模块规范是用来约束每个模块,让其必须按照一定的格式编写.AMD,CMD,CommonJS 是目前最常用的三种模块化书写规范.  1.AMD(Asy ...

  4. Vuex(一)——vuejs的状态管理模式

    一.Vuex是什么? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式. 它采用集中式存储 管理 应用的所有组件 的 状态,并以 相应的规则 保证 状态以一种 可预测的方式 发生变化. ...

  5. 天方夜谈·数据结构·List

    在战场上杀不死的敌人,永远也别想打败他,他就像幽灵横亘在你失败的田地上. 大一下学期,接触到Java程序设计语言,时至今日,才越发觉得知识与技术的海洋是多么多么的浩瀚.......如果说编程语言的一个 ...

  6. mui开发app之cropper裁剪后上传头像的实现

    在大多数app项目中,都需要对用户头像的上传,之前做web开发的时候,我主要是通过input type=file的标签实现的,上传后,使用php对图片进行裁剪,这种方式比较传统简单. 此次app开发中 ...

  7. hadoop+hive+spark搭建(三)

    一.spark安装   因为之前安装过hadoop,所以,在“Choose a package type”后面需要选择“Pre-build with user-provided Hadoop [can ...

  8. 关于 vue.js 运行环境的搭建(mac)

    由于本人使用的是mac系统,因此在vue.js 的环境搭建上遇到许许多多的坑.感谢 showonne.yubang 技术指导,最终成功解决.下面是个人的搭建过程,权当是做个笔记吧. 由于mac非常人性 ...

  9. eclipse 创建maven模块

    先创建一个聚合模块. 勾选Create a simple project 点击finish . 看到已经创建好了这个聚合. 接下来我们创建子模块.pay-hk  pay-web 两个字模块,前面一个是 ...

  10. java web (j2ee)学习路线 —— 将青春交给命运

    RESON TO DO JAVA WEB:1.JAVA WEB(企业级)  2.Android和iOS过于火爆并且不兼容 一.JAVA WEB开发需要的知识储备 1.      基本的网页设计语言:H ...