首先两者读取所有文件的方法都是采用迭代的方式,首先用函数A的返回值判断目录下是否有文件,然后返回值合法则在循环中用函数B直到函数B的返回值不合法为止。最后用函数C释放资源。

1、打开目录

#include <sys/types.h>
#include <dirent.h>DIR *opendir(const char *name);

先看Linux的,返回的是DIR*,因此出错时返回NULL(0)。而这里不用关心DIR结构具体定义,只需要知道是对它进行操作(注意:DIR不是保存文件信息的结构)

而Windows的方法很多,包括MFC的CFileFind类、WINAPI的WIN32_FIND_DATA和C运行库的_finddata_t,这里选取最后一种

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

返回类型是intptr_t,这是用来表示两个指针(地址)之间距离的类型(比如对指针类型p1,p2,用intptr_t来接收p1-p2的返回值),比如指针在32位系统上是4个字节,而在64位系统上是8个字节,通过#ifdef宏来实现跨平台的类型。

这里返回值其实是一个标识当前目录下所有文件的HANDLE而不是实际指针类型,所以出错时返回-1而不是0(NULL)。

再看输入参数,第1个参数是filespec(而不是filename),很容易用错,因为它不是像Linux的opendir一样简单地接收目录名,而是接收一个特定格式。比如C:\*.*就代表搜索C盘下所有类型文件,而C:\*.txt则代表搜索C盘下所有txt文件。第2个参数是struct _finddata_t是实际存储文件信息的结构。

2、遍历文件

每个文件都有一个具体的结构来描述它的属性,这里只以文件名作为示例,其他属性不具体探,具体定义可以查找文档。

#include <dirent.h>struct dirent *readdir(DIR *dirp);

Linux下的方法依然很简单,通过第一步得到的DIR*作为输入参数,方法成功则返回指向当前文件的dirent*,struct dirent即保存文件信息的结构

           struct dirent {ino_t          d_ino;       /* Inode number */off_t          d_off;       /* Not an offset; see below */unsigned short d_reclen;    /* Length of this record */unsigned char  d_type;      /* Type of file; not supportedby all filesystem types */char           d_name[256]; /* Null-terminated filename */};

如果读取失败则返回空指针NULL(0)

再看Windows下的方法

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

这里返回值是int,依旧是出错时返回-1。(C没有异常处理机制,而是采用朴素的错误码机制,于是诞生了让初学者感到很困惑的问题:返回0到底是代表正确还是不正确呢?对错误码而言,0往往代表正确,而对指针而言0则代表失败,也就是空指针NULL)

第1个输入参数也是第1个函数的返回值,第2个输入参数也是描述文件的结构体的指针。struct _finddata_t即保存文件信息的结构,它也是个跨(Windows)平台的定义,以32位系统为例

struct _finddata32_t
{unsigned    attrib;__time32_t  time_create;    // -1 for FAT file systems__time32_t  time_access;    // -1 for FAT file systems__time32_t  time_write;_fsize_t    size;char        name[260];
};

3、关闭目录

#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);

Linux下的,输入参数是第1个函数的返回值,而这里返回值不再是指针,而是错误码,因此返回值为0时代表关闭directory stream成功,为-1代表失败

int _findclose(   intptr_t handle
);

Windows下的也一样,输入参数是第1个函数的返回值,返回0代表关闭handle成功,为-1代表失败。

最后分别给出Linux和Windows上遍历目录下所有文件的示例代码(为了简化忽略错误处理)

#include <stdio.h>
#include <dirent.h>int main(int argc, char** argv)
{struct dirent *direntp;DIR *dirp = opendir("/");if (dirp != NULL) {while ((direntp = readdir(dirp)) != NULL)printf("%s\n", direntp->d_name);}closedir(dirp);return 0;
}

// Windows(C++)
#include <stdio.h>
#include <stdlib.h>
#include <io.h>  // windows的CRT库
#include <string>int main()
{_finddata_t fd;intptr_t handle;std::string dir_name = "C:\\";if ((handle = _findfirst((dir_name + "*.*").c_str(), &fd)) != -1) {while (_findnext(handle, &fd) != -1)printf("%s\n", fd.name);}_findclose(handle);return 0;
}

由于Windows下还要对dir_name附上一段字符串所以直接用std::string了,用char数组然后strcpy太麻烦。

对比可以发现,Windows是把文件结构的指针作为输入参数,而Linux则是作为返回参数,Linux下的这种做法更为自然,而且即使用的是C风格,代码也非常简单易懂。

-----------------------------------------------------------下面是之前的错误看法--------------------------------------------------------------

但是要注意,Linux这种做法实际上是动态申请了空间,需要手动free(direntp)来释放内存,虽然APUE上面的示例代码并没有这一步。

-----------------------------------------------------------上面是之前的错误看法--------------------------------------------------------------

readdir是不可重入的函数,按照man的说明,readdir()的返回值会被接下来的调用给重写

The data returned by readdir() may be overwritten by subsequent calls
to readdir() for the same directory stream.

也就是说readdir的实现其实是类似这种

struct dirent *readdir(DIR *dp)
{static struct dirent dir;// ...return &dir;
}

而不是使用动态申请内存然后再返回。修改上面列出的Linux遍历目录的示例代码,在while ((dirent p = readdir(dirp)) != NULL)的循环体内printf后面加一句delete dirp或者free(dirp)都会报错,而且是特别严重的Aborted (core dumped)。

看来当初自作聪明以为APUE上没顾及到内存的释放的我还是太嫩了,继续啃APUE~

转载于:https://www.cnblogs.com/Harley-Quinn/p/6367425.html

Linux和Windows的遍历目录下所有文件的方法对比相关推荐

  1. php 遍历 目录,PHP采用自定义函数实现遍历目录下所有文件的方法

    目录的遍历是PHP程序设计中经常会用到的一个功能,很多PHP项目都有这一功能模块.今天本文就来实例解析一下PHP采用自定义函数实现遍历目录下所有文件的方法.具体方法如下: 方法一:使用readir() ...

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

    From: http://blog.csdn.net/benbon/article/details/1911230 在windows中遍历目录下的所有文件主要是使用FindFirstFile和Find ...

  3. Python遍历目录下的文件(os.walk 、os.listdir的用法)

    Python遍历目录下的文件(os.walk .os.listdir的用法) 最近想从一个目录转移一些文件到另外一个目录,因为文件有指定的后缀,所以想着用python来转移,不做cv工程师,那就涉及到 ...

  4. File类(常用方法、遍历目录下的文件、listFiles()方法和删除文件及目录)

    File类 File类的常用方法 Filie类常用的构造方法 File(String pathname) //通过指定的一个字符串类型的文件路径来创建一个新的File对象 File(String pa ...

  5. JAVA:遍历目录下的文件

    在实际应用中如何查看指定路径下的文件数目,java提供了一种list()函数用于遍历此路径下的所有文件.注意,在遍历的过程中需要指定文件的类型! import java.io.*; import ja ...

  6. 安卓读取mysql数据库文件路径_Android开发实现读取assets目录下db文件的方法示例...

    本文实例讲述了Android开发实现读取assets目录下db文件的方法.分享给大家供大家参考,具体如下: 最近准备打算写一个关于天气预报的app,偶然的机会在一大神的博客上看到了一个获取天气的api ...

  7. Linux下遍历目录下的文件

    方法1: http://tag.csdn.net/Article/ef431d9b-68b3-419f-9f85-1fb9279f904a.html //ListFile.cpp #include & ...

  8. [Linux] Linux 客户端NFS挂载后目录下中文名文件乱码

    0x0 场景 服务端:Windows 2008R2 NFS共享目录D:/TEST 客户端:Linux/Centos 7.5 Centos 7.5 客户端NFS挂载 Windows2008R2 共享目录 ...

  9. Linux(shell)遍历目录删除指定文件,解决文件夹名称带空格问题

    最近打算把一些学习资源解压上传到阿里网盘上,可是在解压的时候出现了问题,无故产生很多隐藏文件(猪哥mac电脑,用的keka解压软件). 且文件夹层级很多,不可能实现手动一个一个文件夹删除,所以就考虑写 ...

最新文章

  1. 当你工作压力很大的时候
  2. python故事书_python的故事
  3. 2020年日历电子版(打印版)_2020年第11期印花世界电子版/手机版,欢迎在线免费阅读!...
  4. 【福利】囚犯抓绿豆,谁生谁死?
  5. python第五章课后作业_python 入门到实践第五章课后练习
  6. (40)FPGA面试技能提升篇(OAM与SDH协议)
  7. java中什么是线程安全_Java 多线程:什么是线程安全性
  8. c语言实现linux下的top命令来获取cpu利用率_Linux性能调优之CPU性能优化
  9. 赣州计算机教师招聘,江西省赣州市章贡区2019年招聘教师人员岗位表
  10. 并发编程之美(1)并发编程基础
  11. u盘在 计算机管理显示无媒体,urdrive_u盘显示无媒体怎么办_启动盘
  12. 直升机救援机制的发展
  13. 计算机如何重新连接打印机,打印机脱机怎么处理 打印机重新连接方法教程
  14. 计算机无法识别苹果6手机,苹果手机连接电脑没反应,小编教你苹果手机连接电脑没反应怎么办...
  15. Pohlig-Hellman算法求Elgamal算法私钥+大步小步法解决DLP(离散对数问题)
  16. 使用nginx模拟反向代理
  17. 微信小程序输入框字数限制以及计算
  18. shineblink NEO-6M GPS模块获取经纬度/海拔/时间详解
  19. 蕴含连接词的真值表为什么这样定义?
  20. 【读书笔记->统计学】04-01 利用概率理论预测和决策-概率与事件、维恩图、互斥与相交事件、交集与并集概念简介

热门文章

  1. iOS Cookie相关操作
  2. partial equation lecture first order pde lecture 1
  3. UE4 材质:石缝提高混合权重
  4. C#一元运算重载的深入理解
  5. jQuery dataTables 的使用
  6. Flutter入坑分享
  7. 机器学习基础 --- numpy的基本使用
  8. web报告工具FineReport在使用方法和解决方案常见错误遇到(一)
  9. 2.let和const命令
  10. BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]