加入收藏 | 设为首页 | 会员中心 | 我要投稿 济南站长网 (https://www.0531zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

在Linux下和Windows下遍历目录的方法及如何达成一致性操作

发布时间:2016-09-11 05:12:47 所属栏目:Linux 来源:站长网
导读:最近因为测试目的需要遍历一个目录下面的所有文件进行操作,主要是读每个文件的内容,只要知道文件名就OK了。在Java中直接用File类就可以搞定,因为Java中使用

最近因为测试目的需要遍历一个目录下面的所有文件进行操作,主要是读每个文件的内容,只要知道文件名就OK了。在Java中直接用File类就可以搞定,因为Java中使用了组合模式,使得客户端对单个文件和文件夹的使用具有一致性,非常方便。但在C中就不一样了,而且在不同的平台下使用方法也不同。在Linux下实现该功能就非常方便,因为自带有API库,几个函数用起来得心应手(虽然有些小问题,后面说),在Windows下实现就不是那么方便,虽然也有自己的API,但用法有些晦涩难懂,因为没有封装起来,需要自己一步一步进行操作,因为用的是Windows API库函数所以如果对Windows编程不熟悉的话,照搬网上的代码错了也不易调试。为此,我把这些操作都封装成类似Linux下的库函数,一方面简化透明了操作,另一方面(也许更重要)就是移植性,这样将包含该功能的程序从Windows上移植到Linux下就无需改动代码了(删掉实现封装的文件,因为Linux下自带了),当然从Linux下移植到Windows下同样方便(增加实现封装的文件即可),这就是所谓的OCP原则吧(开放封闭原则,具体见:程序员该有的艺术气质—SOLID原则)。好了,首先看下Linux下是如何实现这个功能的。
一、Linux下遍历目录的方法

Linux下实现目录操作的API函数都在头文件dirent.h中,截取部分该文件内容如下:

/** structure describing an open directory. */
typedef struct _dirdesc {
    int    dd_fd;          /** file descriptor associated with directory */
    long    dd_loc;        /** offset in current buffer */
    long    dd_size;       /** amount of data returned by getdirentries */
    char    *dd_buf;       /** data buffer */
    int    dd_len;         /** size of data buffer */
    long    dd_seek;       /** magic cookie returned by getdirentries */
    long    dd_rewind;     /** magic cookie for rewinding */
    int    dd_flags;       /** flags for readdir */
    struct pthread_mutex    *dd_lock;    /** lock */
    struct _telldir *dd_td;    /** telldir position recording */
} DIR;
    
typedef    void *    DIR;
    
DIR    *opendir(const char *);
DIR    *fdopendir(int);
struct dirent *readdir(DIR *);
void     seekdir(DIR *, long);
long     telldir(DIR *);
void     rewinddir(DIR *);
int     closedir(DIR *);
    
    
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[1];          /* file name (null-terminated)*/
};

关键部分就是DIR这个结构体的定义,包括文件描述符、缓冲区偏移、大小、缓冲区内容等,下面定义的就是具体的目录操作函数了,有打开目录、读目录、重置读取位置、关闭目录等,这里我所需要的就是打开、读和关闭这三个最基本的目录操作,下面是使用例子:

#include <stdio.h> 
#include <stdlib.h>    
#include <string.h>  
#include <dirent.h> 
    
#define MAX_LEN 65535
    
int main(void) 
{ 
    DIR *dir; 
    struct dirent *ptr; 
    char *flow[MAX_LEN];
    int num = 0, i = 0;
       
    if ((dir=opendir("./data")) == NULL) 
    { 
        perror("Open dir error..."); 
        exit(1);        
    } 
    // readdir() return next enter point of directory dir
    while ((ptr=readdir(dir)) != NULL) 
    { 
        flow[num++] = ptr->d_name;
//      printf("%sn", flow[num - 1]);
    } 
    
    for(i = 0; i < num; i++)
    {
        printf("%sn", flow[i]);
    }
       
    closedir(dir); 
}

运行结果如下:

在Linux下和Windows下遍历目录的方法及如何达成一致性操作

一看这结果就不对,输出的都是同一个文件名(最后一个文件的文件名), 哪里出了问题呢?将代码中// printf("%sn", flow[num - 1]);这行注释去掉再运行,发现注释处输出的是正确的,两者都是输出的flow数组元素怎么结果不一样呢?经过调试发现是flow[num++] = ptr->d_name;这句代码的问题,因为这是引用拷贝(地址拷贝),所有的flow元素全部指向同一个对象ptr->d_name,虽然ptr->d_name对象每次的内容不同(也就是前面正确输出的原因),但所有内容都共享一个地址,用一个简单的图说明就是:

当然这个问题也比较好解决,也是比较常见的问题,用字符串拷贝或内存拷贝就行了,给flow每个元素重新申请一块内存。

#include <stdio.h> 
#include <stdlib.h>    
#include <string.h>  
#include <dirent.h> 
    
#define MAX_LEN 65535
    
int main(void) 
{ 
    DIR *dir; 
    struct dirent *ptr; 
    char *flow[MAX_LEN];
    int num = 0, i = 0;
       
    if ((dir=opendir("./data")) == NULL) 
    { 
        perror("Open dir error..."); 
        exit(1);        
    } 
    // readdir() return next enter point of directory dir
    while ((ptr=readdir(dir)) != NULL) 
    { 
        flow[num] = (char*)malloc(sizeof(char));
        strcpy(flow[num], ptr->d_name);
        num++;
    } 
    
    for(i = 0; i < num; i++)
    {
        printf("%sn", flow[i]);
    }
       
    closedir(dir); 
}

最终结果就正确了。

在Linux下和Windows下遍历目录的方法及如何达成一致性操作

二、Windows下遍历目录的方法

在Windows下就比较麻烦了,所要用到的函数都在windows.h中,Windows编程本来就比较繁琐,下面就不一一介绍所用到的函数了,直接给出封装的过程。

1. 首先模拟Linux下自带的头文件dirent.h

(编辑:济南站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读