主要用于对目录数据结构和目录操作函数的封装

dirent分析

头文件的路径如下所示:/src/include/port/win32_msvc/dirent.h。该文件主要是win32 native目录操作函数的封装。从源代码目录接口可以看出该文件主要作用是针对win32_msvc的移植文件,这里的port就是移植的意思。这些封装主要依靠DIR和dirent两个结构体来存储信息以及和其他文件进行交互。DIR中有指向char的指针dirname,用于存放目录名的char数组,dirent结构体和handle句柄。dirent结构体包含了存放inodes的d_ino和不需要使用的d_reclen(这连个数据结构在windows上都不需要)以及文件名数组和文件名长度。

struct DIR
{char    *dirname;
struct dirent ret;    /* Used to return to caller */
HANDLE    handle;
};
struct dirent
{long    d_ino;
unsigned short d_reclen;
unsigned short d_namlen;
char    d_name[MAX_PATH];
};

由头文件可以看出主要提供三个函数,即opendir、readdir和closedir三个函数。它们主要的传入传出参数和上述两个结构体相关。下面我们就详细分析这三个函数的详细代码。

/*
* Headers for port/dirent.c, win32 native implementation of dirent functions
*
* $PostgreSQL: pgsql/src/include/port/win32_msvc/dirent.h,v 1.3 2006/10/04 00:30:10 momjian Exp $
*/#ifndef _WIN32VC_DIRENT_H
#define _WIN32VC_DIRENT_H
struct dirent
{long    d_ino;
unsigned short d_reclen;
unsigned short d_namlen;
char    d_name[MAX_PATH];
};typedef struct DIR DIR;DIR    *opendir(const char *);
struct dirent *readdir(DIR *);
int    closedir(DIR *);#endif

opendir打开目录函数,传入参数为目录路径数组。调用win32的GetFileAttributes函数,并对返回值进行检测。使用malloc申请DIR结构体,对dirname和handle信息进行填充,如果路径末尾没有/或\,则直接追加\,最后加上*号,代表所有该目录下的文件。将handle设置为INVALID_HANDLE_VALUE,并将dirent结构体ret中的d_ino和d_reclen设置为0(在Windows下无效)。

DIR *
opendir(const char *dirname)
{DWORD        attr;DIR           *d;/* Make sure it is a directory */attr = GetFileAttributes(dirname);if (attr == INVALID_FILE_ATTRIBUTES){errno = ENOENT;return NULL;}if ((attr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY){errno = ENOTDIR;return NULL;}d = malloc(sizeof(DIR));if (!d){errno = ENOMEM;return NULL;}d->dirname = malloc(strlen(dirname) + 4);if (!d->dirname){errno = ENOMEM;free(d);return NULL;}strcpy(d->dirname, dirname);if (d->dirname[strlen(d->dirname) - 1] != '/' &&d->dirname[strlen(d->dirname) - 1] != '\\')strcat(d->dirname, "\\");        /* Append backslash if not already* there */strcat(d->dirname, "*");    /* Search for entries named anything */d->handle = INVALID_HANDLE_VALUE;d->ret.d_ino = 0;            /* no inodes on win32 */d->ret.d_reclen = 0;        /* not used on win32 */return d;
}

closedir关闭目录文件,传入参数为DIR的指针。如果handle不为INVALID_HANDLER_VALUE则需要关闭句柄,最后释放申请的存放目录名的空间以及输入的DIR结构体的空间。

int
closedir(DIR *d)
{if (d->handle != INVALID_HANDLE_VALUE)FindClose(d->handle);free(d->dirname);free(d);return 0;
}

readdir函数利用opendir处理的DIR结构体中的handle信息,更新DIR结构体中dirent结构体的数据,并将其返回。主要逻辑分两块:如果handle为INVALID_HANDLE_VALUE,则说明刚调用完readdir函数,还没有真正处理该目录下的文件,在这种情况下,使用FIndFirstFile获取第一个文件的handle;如果handle不为INVALID_HANDLE_VALUE,说明已经获取过文件了,则使用FindNextFile函数获取下一个文件的句柄。最终根据获取的文件名和文件名长度更新一下dirent结构体。

struct dirent *
readdir(DIR *d)
{WIN32_FIND_DATA fd;if (d->handle == INVALID_HANDLE_VALUE){d->handle = FindFirstFile(d->dirname, &fd);if (d->handle == INVALID_HANDLE_VALUE){errno = ENOENT;return NULL;}}else{if (!FindNextFile(d->handle, &fd)){if (GetLastError() == ERROR_NO_MORE_FILES){/* No more files, force errno=0 (unlike mingw) */errno = 0;return NULL;}_dosmaperr(GetLastError());return NULL;}}strcpy(d->ret.d_name, fd.cFileName);        /* Both strings are MAX_PATH* long */d->ret.d_namlen = strlen(d->ret.d_name);return &d->ret;
}

window相关API学习

下面使用window的api:FIndFirstFile和FindNextFile做一个小demo测试一下:
FindFirstFile()用于获得指定目录的第一个文件,参数为lpFileName 用于指定搜索目录和文件类型,可以用通配符,初次使用需要注意 \ 需要用转义字符表达。即:D:\C++ 6.0\;
lpFindFileData 用于保存搜索得到的文件信息。FindFirstFile() 返回HANDLE类型,为下一次搜索提供信息。当搜索失败时,返回INVALID_HANDLE_VALUE

HANDLE WINAPI FindFirstFile(_In_   LPCTSTR lpFileName,_Out_  LPWIN32_FIND_DATA lpFindFileData);

FindNextFile() 顾名思义,用于搜索下一个文件,当不存在下一个文件,即搜索完毕后,返回false。hFindFile 上一次FindFirstFile或FindNextFile得到的HANDLE;lpFindFileData 用于保存搜索得到的文件信息。

BOOL WINAPI FindNextFile(_In_   HANDLE hFindFile,_Out_  LPWIN32_FIND_DATA lpFindFileData);

通常,最初的两次搜索得到的文件名为:"." 、"…",分别代表当前目录和上级目录。写代码时需要注意。

HANDLE hFile;LPCTSTR lpFileName = L".\\*.*";    //指定搜索目录和文件类型,如搜索d盘的音频文件可以是"D:\\*.mp3"WIN32_FIND_DATA pNextInfo;    //搜索得到的文件信息将储存在pNextInfo中;hFile = FindFirstFile(lpFileName,&pNextInfo);//请注意是 &pNextInfo , 不是 pNextInfo;if(hFile == INVALID_HANDLE_VALUE){//搜索失败exit(-1);}while(FindNextFile(hFile,&pNextInfo)){if(pNextInfo.cFileName[0] == '.')//过滤.和..continue;cout<<"得到文件:"<<pNextInfo.cFileName<<endl;}

Linux相关API学习

既然是移植,我们来看看Linux下的opendir和readdir以及closedir函数。读取目录的库函数均以getdents系统调用(未纳入SUSv3规范)为基础,但其接口更易于使用。Linux还提供了readdir(2)系统调用(相对于此处描述的readdir(3)库函数),所执行的任务类似于getdents(),也因之而遭废止。
opendir函数打开一个目录,并返回指向该目录的句柄,供后续调用。opendir函数打开由dirpath指定的目录,并返回指向DIR类型结构的指针。该结构即所谓目录流(directory stream),亦即调用者传递给下述其他函数的句柄。一旦从opendir返回,则将目录流指向目录列表的首条记录。

 #include <dirent.h>DIR *opendir(const char *dirpath);Returns directory stream handle, or NULL on error

readdir函数从一个目录流中读取连续的条目。每调用一次,就会从dirp所指代的目录流中读取下一条目录条目,并返回一个指针,指向经静态分配而得到的dirent类型结构,内含与条目相关的如下信息,每次调用都会覆盖该结构。下面对dirent的定义略去了各种非标准字段,比如d_type字段(DT_REG普通文件、DT_DIR目录、DT_LNK符号链接、DT_FIFO)

#inclue <dirent.h>
struct dirent * readdir(DIR *dirp)
Returns pointer to a statically allocated structure describing next directory entry, or NULL on end-of-directory or errorstruct dirent{ino_t d_ino;    // File i-node numberchar d_name[];  // Null-terminated name of file
}

路径名由之前调用opendir时指定的dirpath参数与/字符以及d_name字段的返回值拼接组成。readdir返回时并未对文件名进行排序,而是按照文件在目录中出现的天然次序(这取决于文件系统向目录添加文件时所遵循的次序,及其在删除文件后对目录列表中空隙的填补方式)。一旦遇到目录结尾或是出错,readdir将返回NULL,针对后一种情况,还会设置errno以示具体错误。

errno = 0;
direntp = readdir(dirp);
if(direntp == NULL){if(errno != 0){// Handle error}else{// We reached end of directory}
}

closedir函数由dirp指代、处于打开状态的目录流关闭,同时释放流所使用的资源

#include <dirent.h>
int closedir(DIR *dirp);
Returns 0 on success or -1 on error

PG目录操作封装——dirent一:postgresql-8.4.1\src\port\dirent.c相关推荐

  1. 时间:2014年3月27日文件和目录操作函数

    主要内容: 目录操作:打开.读取.关闭.创建.重命名.删除 文件操作:打开.读.写.关闭.重命名.删除 信息获取函数 filemtime() filesize() file_exists()  is_ ...

  2. Java编程的逻辑 (59) - 文件和目录操作

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  3. ideajava目录显示类成员_c++ 目录操作

    一.源代码说明 本文介绍的是ccfree框架的目录操作函数和类. 函数和类的声明文件是ccfree/_ccfree.h. 函数和类的定义文件是ccfree/_ccfree.cpp. 示例程序位于ccf ...

  4. Linux系统常用目录操作函数

    参考<Linux程序设计>第二版P103 扫描目录: #include <stdio.h> #include <stdlib.h> #include <str ...

  5. Linux C高级编程——目录操作

    Linux C目录操作 宗旨:技术的学习是有限的,分享的精神是无限的. Linux思想"一切皆文件",目录也是文件,只是存储的内容有别于普通文件.目录文件中存储的该目录下所有的文件 ...

  6. android文件读取工具类,Android 下读取Assets Properties操作封装工具类

    Android 下读取Assets Properties操作封装工具类 发布时间:2018-06-03作者:laosun阅读(2081) 为了方便使用,首先创建BaseApplication类,如下所 ...

  7. AIX 文件操作和AIX 目录操作

    1.文件类型 ●普通文件 包括用户和系统的各种文本文件.代码文件.程序文件和数据文件等等. ●目录 包括文件和子目录信息,目录采用倒树状结构. ● 特殊文件 表示物理或逻辑设备,这些文件存放在 /de ...

  8. freecplus框架-目录操作

    文章目录 一.源代码说明 二.创建目录 三.获取目录下的文件信息 四.获取视频教程 五.版权声明 一.源代码说明 freecplus是一个Linux系统下的C/C++开源框架,源代码请前往C语言技术网 ...

  9. Linux系统下文件与目录操作讲解

    Linux系统下文件与目录操作 在Linux系统中有一句话叫做,一切皆文件.上节我们说的I/O操作,对于普通I/O操作,都是打开.读写.关闭.这节我们通过stat结构体来了解文件的一些基本信息和本质特 ...

  10. 目录操作的相关API 和 获取文件的属性信息

    目录 一,目录操作的相关API 1,创建或删除一个空目录 2,打开目录 3,读一个目录 4,关闭一个目录 二,获取文件的属性信息 1, stat,fstat,lstat 用来获取文件的属性信息 2,a ...

最新文章

  1. Tech·Ed 2006博客园聚会
  2. 我在51CTO微职位学软考——网络工程师
  3. Office2013 分享
  4. Sass--@-Rules
  5. 困难动态规划系列、经典的正则表达式和通配符匹配问题(难题)
  6. 数据写入规则IBufferWriterT
  7. 刘小乐教授 - 生物信息学云论坛第三场报告会
  8. C++ 面向对象程序三大特性之 多态
  9. Leetcode每日一题:424.longest-repeating-character-replacement(替换后的最长重复字符)
  10. Python Imaging Library: ImageTk Module(图像Tkinter模块)
  11. 内连接、外连接和全连接的区别
  12. WordPress优化攻略:全面提升WP网站速度仅需3个加速方法和1个插件
  13. 计算机一级excel典型试题,最新excel计算机一级试题合集
  14. Windows批量快速删除大量文件
  15. 什么叫DMZ区?DMZ区它有什么作用?
  16. 1046 划拳 (15分)
  17. android app开机启动画面,Android-如何设置APP开机启动(图文)
  18. 阿里二面:设计一个电商平台积分兑换系统!
  19. jsp mysql电影网站_JSP+Servlet+C3P0+Mysql实现的YCU movies电影网站
  20. 对开发初步认识和体验

热门文章

  1. fftshift使用
  2. 一文学会「内存映射」
  3. PCL_点云数据处理方法概述
  4. 360手机助手下载|360手机助手下载
  5. 卫星电话是直接与卫星通信还是通过地面站?
  6. 勒索病毒代码python_一份勒索病毒解密工具的整理汇总
  7. 网页加载CAD图纸的两个方案对比说明
  8. 《网络运维 - 基础知识》
  9. c语言的单片机delay延时函数详解
  10. sql 查询结果随机排序