1. 程式人生 > >windows下類似linux readdir()讀取檔案

windows下類似linux readdir()讀取檔案

仿寫標頭檔案 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;
}

結果

注意結果裡面有 “..” 上級目錄,順序是按照字母表順序讀取

這裡寫圖片描述