windows下类似linux readdir()读取文件

原创 2016年05月04日 11:02:29

仿写头文件 dirent.h

模拟linux下头文件 myDirent.h

#ifndef MYDIRENT_H
#define MYDIRENT_H

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 */
} DIR;

# define __dirfd(dp)    ((dp)->dd_fd)

DIR *opendir(const char *);
struct dirent *readdir(DIR *);
void rewinddir(DIR *);
int closedir(DIR *);

#include <sys/types.h>

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)*/
};

#endif

实现函数 cpp

windows下仿写opendir() readdir() closedir()
利用FindFirstFile() FindNextFile() 这两个windows函数

myDirent.cpp

#include <iostream>
#include <string>
#include <stdio.h>
#include <windows.h>

#include "myDirent.h"

static HANDLE hFind;

DIR *opendir(const char *name)
{
    DIR *dir;
    WIN32_FIND_DATA FindData;
    char namebuf[512];

    //int sprintf ( char * str, const char * format, ... ); Write formatted data to string
    sprintf(namebuf, "%s\\*.*", name);

    hFind = FindFirstFile(namebuf, &FindData);
    if (hFind == INVALID_HANDLE_VALUE)
    {
        printf("FindFirstFile failed (%d)\n", GetLastError());
        return 0;
    }

    dir = (DIR *)malloc(sizeof(DIR));
    if (!dir)
    {
        printf("DIR memory allocate fail\n");
        return 0;
    }

    memset(dir, 0, sizeof(DIR));
    dir->dd_fd = 0;   // simulate return  

    return dir;
}
struct dirent *readdir(DIR *d)
{
    int i;

    BOOL bf;
    WIN32_FIND_DATA FileData;
    if (!d)
    {
        return 0;
    }

    bf = FindNextFile(hFind, &FileData);
    //fail or end  
    if (!bf)
    {
        return 0;
    }

    struct dirent *dir = (struct dirent *)malloc(sizeof(struct dirent) + sizeof(FileData.cFileName));

    for (i = 0; i < 256; i++)
    {
        dir->d_name[i] = FileData.cFileName[i];
        if (FileData.cFileName[i] == '\0') break;
    }
    dir->d_reclen = i;
    dir->d_reclen = FileData.nFileSizeLow;

    //check there is file or directory  
    if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    {
        dir->d_type = 2;
    }
    else
    {
        dir->d_type = 1;
    }

    return dir;
}
int closedir(DIR *d)
{
    if (!d) 
        return -1;
    hFind = 0;
    free(d);
    return 0;
}

测试一下

int main()
{
    // use as readdir() in Linux
    DIR *dir;
    struct dirent *ptr;

    char *flow[65536];
    int num = 0, i = 0;

    if ((dir = opendir("E:\\data_of_weibo\\data_washed\\event_max_time")) == NULL) {
        std::cerr << "open dir error." << std::endl;
        return false;
    }

    while ((ptr = readdir(dir)) != NULL) {
        flow[num] = (char *)malloc(sizeof(char));
        strcpy(flow[num], ptr->d_name);             //char d_name[1];
        num++;
    }

    // output test
    for (i = 0; i < num; ++i) {
        if (strcmp(flow[i], "..") == 0 || strcmp(flow[i], ".") == 0)
            std::cout << "find last directory." << std::endl;
        else
            std::cout << std::string(flow[i]) << std::endl;
    }
    std::cout << "total file: " << num - 1 << std::endl;

    closedir(dir);

    std::cout << "Press any key to continue.." << std::endl;
    getchar();

    return 0;
}

update:

//上面的写法,strcpy拷贝之后free flow数组会出问题,可能是覆盖了维护数据结构,改一下

int main()
{
    // use as readdir() in Linux
    DIR *dir;
    struct dirent *ptr;

    std::vector<std::string> resVec;

    int num = 0, i = 0;

    if ((dir = opendir("E:\\data_of_weibo\\data_washed\\event_max_time")) == NULL) {
        std::cerr << "open dir error." << std::endl;
        return false;
    }

    while ((ptr = readdir(dir)) != NULL)
        resVec.push_back(std::string(ptr->d_name));     //char d_name[1];

    for (unsigned j = 0; j < resVec.size(); j++)
        std::cout << resVec.at(j) << std::endl;     //包含 ".." 上级目录

    std::cout << resVec.size() << std::endl;

    closedir(dir);

    std::cout << "Press any key to continue.." << std::endl;
    getchar();

    return 0;
}

结果

注意结果里面有 “..” 上级目录,顺序是按照字母表顺序读取

这里写图片描述

版权声明:本文为博主原创文章,未经博主允许不得转载。

linux 下opendir readdir 在windows下的替代函数

最近在做一个linux下c程序到windows下的移植工程,在移植过程中发现windows下对opendir readdir存在很大问题,经多方查找,终于在http://www.tenouk.com/...
  • killerzhou
  • killerzhou
  • 2008年04月17日 16:20
  • 5268

opendir 、readdir 小结

1. opendir() 头文件   #include   #include 函数原型   DIR* opendir (const char * path ); (获取path子目录...
  • lin_FS
  • lin_FS
  • 2012年03月09日 10:37
  • 28517

opendir---opendir() 函数打开目录句柄。

  • qq_34242581
  • qq_34242581
  • 2016年11月01日 14:50
  • 323

Linux和Windows下文件和目录的相关属性及操作

我们知道C/C++都提供了标准的文件I/O库以便我们对文件进行读写。但我们无法通过标准的I/O库对文件系统进行更进一步的操作。因为这设计到具体操作系统中文件系统的设计。在Linux和Windows程序...
  • anonymalias
  • anonymalias
  • 2013年11月30日 17:52
  • 6516

关于遍历linux的文件目录的坑- readdir

去年给公司写了一个配置服务器,目的是解决运维的工作量太大,而且传送服务器需要的配置文件需要脚本传送到各个服(每个服ip不一样,需要scp),然后再刷新通知各个GameServer,中间有没有传送失败并...
  • pbymw8iwm
  • pbymw8iwm
  • 2015年08月20日 12:21
  • 3945

Linux下readdir

dir
  • u014646950
  • u014646950
  • 2016年08月24日 14:47
  • 364

是readdir,还是readdir_r

readdir的原型如下: struct dirent *readdir(DIR *dirp);          因为内部使用了静态数据,所以readdir被认为不是线程安全的函数,POSIX[...
  • gqtcgq
  • gqtcgq
  • 2015年12月19日 18:01
  • 2933

window下实现软连接,像linux一样的软链接

转自:http://bbs.vpigirl.com/forum.php?mod=forumdisplay&fid=52 Linux下有一个软连接的功能,window下对应的可以用快捷方式来实现...
  • zhanlanmg
  • zhanlanmg
  • 2015年03月11日 08:59
  • 2581

Windows IOCP模型与Linux EPOLL模块之比较

一:IOCP和Epoll之间的异同。 异: 1:IOCP是WINDOWS系统下使用。Epoll是Linux系统下使用。 2:IOCP是IO操作完毕之后,通过Get函数获得一个完成的事件通知。 ...
  • educast
  • educast
  • 2013年11月12日 11:55
  • 7765

readdir() 获取文件类型

readdir() 获取文件类型
  • lile777
  • lile777
  • 2015年04月15日 09:01
  • 695
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:windows下类似linux readdir()读取文件
举报原因:
原因补充:

(最多只允许输入30个字)