C/C++ 遍历目录文件,默认目录下

每次遇到这样的问题总会折腾很久,到网上搜,或者查资料,弄了很多次,但就是没记住,这次写程序又遇到了,干脆就把它都弄清楚了,然后顺便在这里记录一下,以后再遇到就不用到处去找了。

用 C/C++ 遍历目录文件主要有两种方式,分别对应在 Windows VS 环境下和 Linux\Unix 环境下的方法,它们各自所使用的函数如下:

  1. (Windows VS)_findfirst, _findnext, _findclose
  2. (Linux\Unix)opendir, readdir, closedir

下面就来详细地说说这两种方式

第一(_findfirst, _findnext, _findclose)

  基本流程:_findfirst-->_findnext-->_findclose

 

(1)First Step

_findfirst 的函数原型:

[cpp] view plaincopy

  1. long _findfirst( char *filespec, struct _finddata_t *fileinfo );

它返回一个文件句柄,可以作为其他函数的参数,并将文件名匹配由 filespec 指定的模式的第一个文件的信息保存在 fileinfo 里。例如我要找某个目录下的 txt 文件,那么 fileinfo 就保存了这个目录下第一个 txt 文件的信息,这种情况下我们可以这样来调用这个函数:

[cpp] view plaincopy

  1. long pFile = long _findfirst( "*.txt", fileinfo );

而用来保存文件信息的 fileinfo 是一个数据类型为 _finddata_t 的结构体,在头文件IO.H定义:

[cpp] view plaincopy

  1. struct _finddata_t {
  2. unsigned    attrib;              /*文件属性*/
  3. time_t      time_create;         /*文件创建时间, -1 for FAT file systems */
  4. time_t      time_access;         /*文件最后一次访问的时间 -1 for FAT file systems */
  5. time_t      time_write;          /*文件最后一次写的时间*/
  6. _fsize_t    size;                /*文件大小*/
  7. char        name[_MAX_FNAME];    /*匹配的文件名,不包含目录,_MAX_FNAME在STDLIB.H中定义为256字节*/
  8. };

其中文件属性可以是以下的这些值(MSDN上的说明):

_A_ARCH(存档)

Archive. Set whenever the file is changed, and cleared by the BACKUP command. Value: 0x20

_A_HIDDEN(隐藏文件)

Hidden file. Not normally seen with the DIR command, unless the /AH option is used. Returns information about normal files as well as files with this attribute. Value: 0x02

_A_NORMAL(普通文件,没有读写限制)

Normal. File can be read or written to without restriction. Value: 0x00

_A_RDONLY(只读文件)

Read-only. File cannot be opened for writing, and a file with the same name cannot be created. Value: 0x01

_A_SUBDIR(子目录)

Subdirectory. Value: 0x10

_A_SYSTEM(系统文件)

System file. Not normally seen with the DIR command, unless the /A or /A:S option is used. Value: 0x04

 

(2)Second Step

我们已经读取了第一个文件的信息了,那怎么读取下一个呢,这时候就轮到 _findnext 出马了,同样我们先看看其函数原型:

[cpp] view plaincopy

  1. int _findnext( long handle, struct _finddata_t *fileinfo );

这个函数调用如果成功就返回0,否则返回-1。它将下一个文件名匹配 filespec 的文件的信息保存在 fileinfo 里面,handle 是调用 _findfirst 时返回的句柄。比如说我们这里的例子,要得到下一个txt文件的信息,我们可以这样调用函数

[cpp] view plaincopy

  1. _findnext(pFile, fileinfo);

所以我们不断调用 _findnext 直到它返回-1就可以遍历所有的txt文件了。

 

(3)Step Three

函数 _findclose 就是做一些收尾工作,关闭文件句柄:

[cpp] view plaincopy

  1. int _findclose( long handle );

同样地,handle 也是调用 _findfirst 时返回的句柄。

 

(4)Final

综上所述,遍历某个目录下指定的文件(所有文件则用*表示)可以这样写:

[cpp] view plaincopy

  1. #include <io.h>
  2. int main()
  3. {
  4. struct _finddata_t fileinfo;
  5. long hFile;
  6. if((hFile = _findfirst("*.txt",&fileinfo)) == -1)
  7. return -1;
  8. else {
  9. do {
  10. /*Process File*/
  11. }while (_findnext(hFile,&file)==0);
  12. }
  13. _findclose(hFile);
  14. return 0;
  15. }

第二(opendir, readdir, closedir)

  基本流程:opendir-->readdir-->closedir

 

(1)Step One

使用这些函数我们需要包含头文件 <sys/types.h> 和 <dirent.h>。

我们要读取目录下的文件信息,首先要打开目录,也就是要调用函数 opendir:

[cpp] view plaincopy

  1. DIR *opendir(const char *pathname);

这个函数以目录的路径为参数,如果打开成功,就返回一个DIR类型的指针,相当于上面所说的句柄,用于后续函数调用;否则返回 NULL。所以如果要打开当前目录可以这样调用函数:

[cpp] view plaincopy

  1. DIR *pDir = opendir(".");

这样我们就打开了目录,返回值 pDir 用于接下来函数调用的参数。

 

(2)Step Two

接下来就是读取文件的信息了 ,在 <dirent.h> 中定义了一个结构体 dirent ,用来保存文件信息,定义如下:

[cpp] view plaincopy

  1. struct dirent {
  2. ino_t          d_ino;       /* i-inode number */
  3. off_t          d_off;       /* offset to the next dirent */
  4. unsigned short d_reclen;    /* length of this record */
  5. unsigned char  d_type;      /* type of file */
  6. char           d_name[256]; /* null-terminated filename */
  7. };

这里面其实经常要用到的就是 d_type 和 d_name 这两个字段,分别表示文件类型和文件名。

d_type 表示文件类型,其取值定义如下:

[cpp] view plaincopy

  1. enum
  2. {
  3. DT_UNKNOWN = 0,
  4. # define DT_UNKNOWN DT_UNKNOWN
  5. DT_FIFO = 1,
  6. # define DT_FIFO DT_FIFO
  7. DT_CHR = 2,
  8. # define DT_CHR DT_CHR
  9. DT_DIR = 4,
  10. # define DT_DIR DT_DIR
  11. DT_BLK = 6,
  12. # define DT_BLK DT_BLK
  13. DT_REG = 8,
  14. # define DT_REG DT_REG
  15. DT_LNK = 10,
  16. # define DT_LNK DT_LNK
  17. DT_SOCK = 12,
  18. # define DT_SOCK DT_SOCK
  19. DT_WHT = 14
  20. # define DT_WHT DT_WHT
  21. };

然后使用 readdir 这个函数来读取文件信息:

[cpp] view plaincopy

  1. struct dirent *readdir(DIR *dp);

dp 为调用 opendir 时的返回值。当读取成功时,函数返回一个保存文件信息的 dirent 结构体指针,当到达目录末尾或出错时返回 NULL。每次调用该函数时读取下一个文件的信息,所以不断调用函数直到它返回 NULL,就可以遍历该目录下所有的文件:

[cpp] view plaincopy

  1. struct dirent * ptr = readdir(pDir);

 

(3)Step Three

最后这一步也是收尾工作,关闭目录:

[cpp] view plaincopy

  1. int closedir(DIR *dp);

同样的,dp 为调用 opendir 时的返回值,成功时返回0,失败时返回-1。

[cpp] view plaincopy

  1. closedir(pDir);

 

(4)Final

因此,总的遍历目录文件的程序可以这样写:

[cpp] view plaincopy

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <dirent.h>
  4. int main()
  5. {
  6. DIR* pDir;
  7. struct dirent* ptr;
  8. if( !(dir = opendir(".")) )
  9. return -1;
  10. while( (ptr = readdir(pDir)) != 0 )
  11. {
  12. /*Processing File*/
  13. }
  14. closedir(pDir);
  15. return 0;
  16. }

总结

一般来说,第一种方法只能在 Windows VS 环境下用,而第二种方法只能在 Linux/Unix 环境下使用。因为在用 VS 写程序的过程中想用第二种方法看看能不能用,结果是找不到头文件 <dirent.h>,而且从结构体 dirent 的定义中我们就可以看出,它只能在 Linux 下使用,因为 dirent 的定义中有个字段是表示文件的 i-node number,这个恰恰是在Linux 的文件管理中才有的。当在 Linux 想用第二种方法时则找不到头文件 <io.h>。但网络上可能有一些方法可以两种方法在两个平台上都可以使用,这个我倒没有去搜索相关的资料,如果大家有什么好的办法,可以分享一下。上面的两个程序我都已经测试过了,用的是 VS2012 和 Ubuntu。

另外,由上面的解说可以看到,在 Windows 下可以很容易地读取某一类型的文件的信息(比如 txt 文件),但在 Linux 下则需要多花些功夫(比如要查看 txt 文件,你得读取文件信息然后再判断文件扩展名是不是 .txt)。

时间: 2024-10-11 00:24:01

C/C++ 遍历目录文件,默认目录下的相关文章

Linux的文件与目录权限解析

在Linux中,万事万物皆文件,普通文件是文件,目录是文件,硬件设备也是文件,因此学习了解Linux中的文件非常重要. Linux中有三种文件类型: (1) 普通文件:又分为文本文件和二进制文件 (2) 目录文件:目录文件存储了一组相关文件的位置.大小等与文件有关的信息. (3) 设备文件:I/O设备在Linux中也被看成文件,与普通文件一样处理,这样使文件与设备的操作尽可能统一. 一.Linux文件属性 Linux的文件有很多属性,要查看文件的属性可以用ls -l命令,为了后续的讲解中有操作的

Shell命令-搜索文件或目录之which、find

文件及内容处理 - which.find 1. which:查找二进制命令,按环境变量PATH路径查找 which命令的功能说明 which 命令用于查找文件.which 指令会在环境变量 $PATH 设置的目录里查找符合条件的文件. which命令的语法格式 which [options] [--] programname [...]which [参数...] [命令] which命令的常用参数说明: which 参数不多,表1为 which 命令的参数及说明: 表1: which 命令的参数

[zz]如何控制ftp用户可以切换到ftp home目录的上级目录

mkdir /var/ftp //(创建ftp目录) chown ftp /var/ftp/ //(让用户ftp成为 /var/ftp的所有者,后面我们会禁用匿名访问,所以这步是必须的) chmod o-x /var/ftp/* (撤销用户ftp 对/var/ftp/下的所有文件的执行权限,这样会更安全些.*/ passwd ftp //(设置用户ftp的密码) vim /etc/password //(编辑password文件,将ftp的home目录更为:/var/ftp) vim /etc/

遍历指定文件夹下的所有图片,并复制到指定目录下

import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; public class Copy { /** * 遍历文件夹下的所有图片文件,并复制到指定文件夹下 */ static String srcfile = "E:/I

遍历某个文件夹(目录)下的所有文件

http://www.nowamagic.net/php/php_TraversalAllFilesInDir.php 有这么一个需求,需要遍历某个文件夹(目录)下的所有文件.下面是解决这个问题所写的PHP代码,在这里记录一下. 第一种实现办法是用dir返回对象,第二种实现办法:用readdir()函数. <?php /********************** 一个简单的目录递归函数 第一种实现办法:用dir返回对象 ***********************/ function tre

小白日记37:kali渗透测试之Web渗透-手动漏洞挖掘(三)-目录遍历、文件包含

手动漏洞挖掘 漏洞类型 #Directory traversal 目录遍历[本台机器操作系统上文件进行读取] 使用者可以通过浏览器/URL地址或者参数变量内容,可以读取web根目录[默认为:/var/www/]之外的其他操作系统文件(如:/etc/passwd/).形成根源:目录权限限制不严格 #File include文件包含[1.include本地文件包含LFI:2.远程系统文件包含RFI(可传入木马)] 通常为如include函数,可以将web根目录以外的目录包含进来.根源:include

[转载]python文件和目录操作方法大全(含更改文件夹下所有文件名称的实例)

http://blog.csdn.net/u010159842/article/details/53084067 一.Python中对文件.文件夹操作时经常用到的os模块和shutil模块常用方法.1.得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd()2.返回指定目录下的所有文件和目录名:os.listdir()3.函数用来删除一个文件:os.remove()4.删除多个目录:os.removedirs(r"c:\python")5.检验给出的路径是否是一

linux系统下修改文件夹目录权限

linux系统下修改文件夹目录权限 文件夹权限问题 Linux.Fedora.Ubuntu修改文件.文件夹权限的方法差不多.很多人开始接触Linux时都很头痛Linux的文件权限问题.这里告诉大家如何修改Linux文件-文件夹权限.以主文件夹下的一个名为cc的文件夹为例. 下面一步一步介绍如何修改权限: 1.打开终端.输入su(没 Linux.Fedora.Ubuntu修改文件.文件夹权限的方法差不多.很多人开始接触Linux时都很头痛Linux的文件权限问题.这里告诉大家如何修改Linux文件

攻城狮在路上(叁)Linux(十五)--- 文件与目录的默认权限与隐藏权限

一.文件默认权限:umask <==需要被减去的权限. 1.umask指的是当前用户在新建文件或者目录时的默认权限,如0022; 2.默认情况下,用户创建文件的最大权限为666; 创建目录的最大权限为777. 3.最终权限 = 最大权限 - umask; <== 此处注意并非是数值直接相减. 4.设置umask: umask 002; 5.由上述条件,自己判断用户新建文件或目录的最终权限. 二.文件的隐藏属性: chattr.lsattr , 隐藏属性对于系统安全有很大的帮助. chattr