头文件 :
#include<dirent.h>

#include<sys/types.h>

在Linux下opendir()、readdir()和closedir()这三个函数主要用来遍历目录。

int stat(const char *restrict pathname, struct stat *restrict buf);
提供文件名字,获取文件对应属性。

opendir():
函数原型:
DIR * opendir(const char* path);

打开一个目录,在失败的时候返回NULL(如果path对应的是文件,则返回NULL);
opendir函数的作用是打开一个目录并建立一个目录流。如果成功,它返回一个指向DIR结构的指针,该指针用于读取目录数据项。

opendir在失败时会返回一个空指针。注意,目录流用一个底层文件描述符来访问目录本身,所以如果打开的文件过多,opendir可能会失败。

DIR 结构体的原型为:struct_dirstream

在linux系统中:

typedef struct __dirstream DIR;

       struct __dirstream
       {
         void *__fd; /* `struct hurd_fd' pointer for descriptor.   */
         char *__data; /* Directory block.   */
         int __entry_data; /* Entry number `__data' corresponds to.   */
         char *__ptr; /* Current pointer into the block.   */
         int __entry_ptr; /* Entry number `__ptr' corresponds to.   */
         size_t __allocation; /* Space allocated for the block.   */
         size_t __size; /* Total valid data in the block.   */
         __libc_lock_define (, __lock) /* Mutex lock for this structure.   */
        };

readdir():
函数原型:
struct dirent * readdir(DIR * dir_handle);
本函数读取dir_handle目录下的目录项,如果有未读取的目录项,返回目录项,否则返回NULL。
循环读取dir_handle,目录和文件都读

返回dirent结构体指针,dirent结构体成员如下,(文件和目录都读)

  struct dirent

  {

  long d_ino; /* inode number 索引节点号 */

  off_t d_off; /* offset to this dirent 在目录文件中的偏移 */

  unsigned short d_reclen; /* length of this d_name 文件名长 */

  unsigned char d_type; /* the type of d_name 文件类型 */

  char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符*/

  }

readdir函数将返回一个指针,指针指向的结构里保存着目录流drip中下一个目录项的有关资料。每调用一次readdir,就有一个文件名保存到d_name [NAME_MAX+1]中,后续的readdir调用将返回后续的目录项,如果发生错误或者到达目录尾,readdir将返回NULL。POSIX兼容的系统在到达目录尾时会返回NULL,但并不改变errno的值,在发生错误时才会设置errno。

  注意,如果在readdir函数扫描目录的同时还有其他进程在该目录里创建或删除文件,readdir将不保证能够列出该目录里的所有文件(和子目录)。

  dirent结构中包含的目录数据项内容包括以下部分:

  ino_t d_ino——文件的inode节点号

  char d_name[ ]——文件的名字

  要想进一步了解目录中某个文件的详细资料,则需要使用在本章前面介绍过的stat调用。

closedir():
函数原型:

int closedir(DIR * dir_handle);

telldir函数

  telldir函数的返回值记录着一个目录流里的当前位置。你可以在随后的seekdir调用中利用这个值来重置目录扫描到当前位置

seekdir函数

  seekdir函数的作用是设置目录流dirp的目录项指针。loc的值用来设置指针位置,它应该通过前一个telldir调用获得。

最近在看Linux下文件操作相关章节,遇到了这么几个结构体,被搞的晕乎乎的,今日有空,仔细研究了一下,受益匪浅。

首先说说DIR这一结构体,以下为DIR结构体的定义:

  1. struct __dirstream
  2. {
  3. void *__fd;
  4. char *__data;
  5. int __entry_data;
  6. char *__ptr;
  7. int __entry_ptr;
  8. size_t __allocation;
  9. size_t __size;
  10. __libc_lock_define (, __lock)
  11. };
  12. typedef struct __dirstream DIR;

DIR结构体类似于FILE,是一个内部结构,以下几个函数用这个内部结构保存当前正在被读取的目录的有关信息(摘自《UNIX环境高级编程(第二版)》)。函数 DIR *opendir(const char *pathname),即打开文件目录,返回的就是指向DIR结构体的指针,而该指针由以下几个函数使用:

  1. struct dirent *readdir(DIR *dp);
  2. void rewinddir(DIR *dp);
  3. int closedir(DIR *dp);
  4. long telldir(DIR *dp);
  5. void seekdir(DIR *dp,long loc);

关于DIR结构,我们知道这么多就可以了,没必要去再去研究他的结构成员。

接着是dirent结构体,首先我们要弄清楚目录文件(directory file)的概念:这种文件包含了其他文件的名字以及指向与这些文件有关的信息的指针(摘自《UNIX环境高级编程(第二版)》)。从定义能够看出,dirent不仅仅指向目录,还指向目录中的具体文件,readdir函数同样也读取目录下的文件,这就是证据。以下为dirent结构体的定义:

  1. struct dirent
  2. {
  3.   long d_ino; /* inode number 索引节点号 */
  4.   
  5. off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
  6.   
  7. unsigned short d_reclen; /* length of this d_name 文件名长 */
  8.   
  9. unsigned char d_type; /* the type of d_name 文件类型 */
  10.   
  11. char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
  12. }

从上述定义也能够看出来,dirent结构体存储的关于文件的信息很少,所以dirent同样也是起着一个索引的作用,如果想获得类似ls -l那种效果的文件信息,必须要靠stat函数了。

通过readdir函数读取到的文件名存储在结构体dirent的d_name成员中,而函数

int stat(const char *file_name, struct stat *buf);

的作用就是获取文件名为d_name的文件的详细信息,存储在stat结构体中。以下为stat结构体的定义:

  1. struct stat {
  2. mode_t     st_mode;       //文件访问权限
  3. ino_t      st_ino;       //索引节点号
  4. dev_t      st_dev;        //文件使用的设备号
  5. dev_t      st_rdev;       //设备文件的设备号
  6. nlink_t    st_nlink;      //文件的硬连接数
  7. uid_t      st_uid;        //所有者用户识别号
  8. gid_t      st_gid;        //组识别号
  9. off_t      st_size;       //以字节为单位的文件容量
  10. time_t     st_atime;      //最后一次访问该文件的时间
  11. time_t     st_mtime;      //最后一次修改该文件的时间
  12. time_t     st_ctime;      //最后一次改变该文件状态的时间
  13. blksize_t st_blksize;    //包含该文件的磁盘块的大小
  14. blkcnt_t   st_blocks;     //该文件所占的磁盘块
  15. };

这个记录的信息就很详细了吧,呵呵。

最后,总结一下,想要获取某目录下(比如a目下)b文件的详细信息,我们应该怎样做?

首先,我们使用opendir函数打开目录a,返回指向目录a的DIR结构体c。

接着,我们调用readdir( c)函数读取目录a下所有文件(包括目录),返回指向目录a下所有文件的dirent结构体d。

然后,我们遍历d,调用stat(d->name,stat *e)来获取每个文件的详细信息,存储在stat结构体e中。

总体就是这样一种逐步细化的过程,在这一过程中,三种结构体扮演着不同的角色。

三个函数介绍完了,直接来一个例子吧:
**********************************************SearchDir.c****************************************************
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
char filename[256][256];
int len = 0;
int trave_dir(char* path, int depth)
{
    DIR *d; //声明一个句柄
    struct dirent *file; //readdir函数的返回值就存放在这个结构体中
    struct stat sb;    
    
    if(!(d = opendir(path)))
    {
        printf("error opendir %s!!!/n",path);
        return -1;
    }
    while((file = readdir(d)) != NULL)
    {
        //把当前目录.,上一级目录..及隐藏文件都去掉,避免死循环遍历目录
        if(strncmp(file->d_name, ".", 1) == 0)
            continue;
        strcpy(filename[len++], file->d_name); //保存遍历到的文件名
        //判断该文件是否是目录,及是否已搜索了三层,这里我定义只搜索了三层目录,太深就不搜了,省得搜出太多文件
        if(stat(file->d_name, &sb) >= 0 && S_ISDIR(sb.st_mode) && depth <= 3)
        {
            trave_dir(file->d_name, depth + 1);
        }
    }
    closedir(d);
    return 0;
}
int main()
{
    int depth = 1;
    int i;
    trave_dir("/usr/keygoe/ini/", depth);
    for(i = 0; i < len; i++)
    {
        printf("%s/t", filename[i]);
    }
    printf("/n");
    return 0;
}

文件操作opendir()/readdir()/closedir()/stat()相关推荐

  1. linux opendir readdir closedir 的使用

    2012-06-04 10:27 linux opendir readdir closedir 的使用 在Linux下opendir().readdir()和closedir()这三个函数主要用来遍历 ...

  2. 《Linux系统调用:opendir,readdir,closedir,rewinddir》

    一.介绍 opendir()和 fdopendir() 都是打开一个目录返回DIR 类型指针(目录的句柄) closedir() 关闭打开的目录句柄 readdir() 从一个目录流读取连续的条目,返 ...

  3. opendir/readdir/closedir函数

    opendi(3)/readdir(3)/closedir(3) 用于遍历目录数据块中的记录.opendir打开一个目录,返回一个DIR *指针代表这个目录,它是一个类似FILE *指针的句柄,clo ...

  4. php 语言文件操作,php中目录文件操作详谈

    php中目录文件操作详谈 首先介绍的是一个从目录读取的函数,opendir(),readdir(),closedir(),使用的时候是先打开文件句柄,以下是小编整理的php中目录,文件操作详谈,欢迎来 ...

  5. Java实现opendir的api_linux文件操作API

    from http://blog.chinaunix.net/uid-21411227-id-1826945.html 2010.11 1.Linux文件系统Linux支持多种文件系统,如ext.ex ...

  6. php dir opendir,php中目录操作opendir()、readdir()及scandir()用法示例

    本文实例讲述了php中目录操作opendir().readdir()及scandir()用法.分享给大家供大家参考,具体如下: opendir(path,context)若成功,则该函数返回一个目录流 ...

  7. PHP文件上传和文件操作案例

    <?php /**文件配置变量$dirname是目录名称*/ session_start(); $dirname = 'upload'; $fileClass = new fileClass($ ...

  8. linux文件操作函数程序,linux 文件操作函数

    文件操作(Linux) 常用linux函数库中的基本函数 1. close函数,关闭文件 2. creat函数,建立文件 3. dup.dup2函数,复制文件描述词 4. fcntl函数,文件描述词操 ...

  9. 前端学PHP之文件操作

    前面的话 在程序运行时,程序本身和数据一般都存在内存中,当程序运行结束后,存放在内存中的数据被释放.如果需要长期保存程序运行所需的原始数据,或程序运行产生的结果,就需要把数据存储在文件或数据库.一般地 ...

最新文章

  1. linux下c语言俄罗斯方块,C语言实现俄罗斯方块源代码
  2. python写入一个文件之前可以不打开_如何用python实现真正的打开和关闭文件
  3. 《The Last Night》美术分析
  4. git报错:fatal: remote origin already exists
  5. PC端与虚拟机内容拷贝
  6. 程序员为什么越老越贬值的厉害?
  7. jsp mysql电子档案管理系统_学生档案管理系统的设计与实现(JSP,MySQL)(含录像)
  8. Blockchain.com将于今日7:59暂停XRP交易
  9. url请求特殊字符转换
  10. 训练集、验证集、测试集
  11. 经典机器学习系列(六)【集成学习】
  12. c# export server 调用sql_C# 如何调用 SPL 脚本
  13. ubuntu14.04 caffe安装前先要将gcc版本降到4.7.x
  14. 微信小程序获取用户信息并存入数据库
  15. Http 资源服务器 搭建 HFS
  16. 深度学习caffe--手写字体识别例程(一)——运行手写字体识别例程
  17. 魅族u20怎么刷Android,魅族魅蓝U20/U10一键Root权限获取+USB驱动安装
  18. 哲学家就餐问题-中断解决
  19. c语言pow函数算力,c语言pow函数算力
  20. 阿里面试——机器学习岗四个面试案例

热门文章

  1. matlab 色块图,matlab绘制矩阵色块图
  2. python经典类和新式类_python中经典类和新式类的区别
  3. SICP:费马小定理与素数检测
  4. 对不可能之事持一种健康的漠视
  5. 三维可视化技术在超超临界锅炉防磨防爆中的应用
  6. 联想造超级计算机,联想将造超级计算机 性能10倍于IBM蓝色基因
  7. 机器学习入门(七):多项式回归, PolynomialFeatures详解
  8. librosa与python_speech_features
  9. JAVA如何调用API
  10. Intent Service 和Service的区别