本文可转载,转载请注明出处: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. WebForm捆绑压缩js和css(WebForm Bundling and Minification)

    .net framework 4以上,可以使用Microsoft.AspNet.Web.Optimization 新建4.0项目 Nuget搜索optimization,安装第一个包 加入Bundle ...

  2. 看看我做的一款 时间轴 插件 timegliderJs

    TimegliderJs 是一款基于jQuery的时间轴插件.完成后效果. 介绍 Timeglider JS是一个由javascript支持缩放,数据驱动的时间轴组件.非常适合显示项目历史,项目计划及 ...

  3. angular 实现自定义样式下拉菜单

    自己闲着没事写了一个自定义的下拉菜单希望和大家交流一下!望能和大神们成为朋友. 下面上代码: <!doctype html> <html lang="en" ng ...

  4. [ext4]磁盘布局 - inode bitmap & table

    在[磁盘布局 group部分]已经介绍过ext4的整体布局,其中存在两个与inode有关的名称:inode bitmap和inode table. Inode bitmap,用于表示inode tab ...

  5. TP5常用命令符操作

    ThinkPHP5常用命令符操作   1. 模块自动生成指令:   默认会读取应用目录application下面的build.php作为自动   生成的定义文件,如果你的定义文件位置不同,则需要使用 ...

  6. Node.js项目APM监控之New Relic

    现在上一个项目,如果没有APM监控服务或应用的运行性能参数,等于是一架没有盲降系统的飞机正在盲降,结果会很悲催.出现了访问失效等问题时,都很难判定是性能瓶颈还是一个藏的深的bug,汇报的时候一顿眼晕, ...

  7. 适配器模式(Adpater Pattern)

    适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作. 适配器模式的用途 用电器做例子,笔记本电脑的插头一般都是三相的,即除了阳极.阴极 ...

  8. [linux 整理] linux启动过程3

    本文介绍linux启动过程的第三步 busybox--------------------> rc init busybox位置即内容 busybox/init/init.c 1.各种设置信号 ...

  9. iOS 关于UITableView的黑科技

      UITableView是我们最常用的控件了,今天我就来介绍一些关于UITableView的黑科技和一些注意的地方. 1.修改左滑删除按钮的高度   左滑删除这是iOS最先发明的,之后安卓开始模仿. ...

  10. 初识Java反射

    要详细的了解Java反射,就得要了解Java的类加载以及何为运行时动态加载等等概念.本文抛开其余概念,简单介绍Java反射,详细介绍会在以后有一个系统而全面的认识过后展开. 反射是Java被视为动态语 ...