C/C++遍歷目錄下的全部文件(Windows/Linux篇,超詳細)

本文可轉載,轉載請註明出處:http://www.cnblogs.com/collectionne/p/6815924.htmlhtml

 

前面的一篇文章咱們講了用Windows API遍歷一個目錄下的全部文件,此次咱們講用一種Windows/Linux通用的方法遍歷一個目錄下的全部文件。ios

 

Windows/Linux的IDE都會提供一個頭文件——<io.h>。看名字,彷佛是關於I/O的,可是實際上它還提供了相似於WIN32_FIND_DATA、FindFirstFile()、FindNextFile()和FindClose()的查找文件的功能。函數

 

_finddata_t結構spa

 

_finddata_t結構用來記錄查找到的文件的信息。實際上有_finddata32_t、_finddata32i64_t、_finddata64i32_t、_finddata64_t、_wfinddata32_t、_wfinddata32i64_t、_wfinddata64i32_t、_wfinddata64_t八個結構,但都只是在32位/64位整數和字符類型上有所區別,但總體上相同。大體定義以下(MSDN):指針

 

struct _finddata_t
{
    unsigned attrib;
    size_t time_create;
    size_t time_access;
    size_t time_write;
    _fsize_t size;
    char name[_MAX_PATH];
};

 

對於不一樣的_finddata_t結構,time_create、time_access和time_write的類型爲_time32_t或_time64_t,size的類型爲_fsize_t或__int64,name爲char[_MAX_PATH]或wchar_t[_MAX_PATH]。code

 

attribhtm

 

unsigned類型,文件屬性。blog

 

time_createci

 

_time32_t/_time64_t類型,文件建立時間(FAT文件系統爲-1)。以UTC格式存儲,若是須要轉換成當地時間,使用localtime_s()。資源

 

time_access

 

_time32_t/_time64_t類型,文件最後一次被訪問的時間(FAT文件系統爲-1)。以UTC格式存儲,若是須要轉換成當地時間,使用localtime_s()。

 

time_write

 

_time32_t/_time64_t類型,文件最後一次被寫入的時間。以UTC格式存儲,若是須要轉換成當地時間,使用localtime_s()。

 

size

 

_fsize_t/__int64類型,文件的長度(以字節爲單位)。

 

name

 

char[_MAX_PATH]/wchar_t[_MAX_PATH]類型,文件/目錄名,不包含路徑。

 

對於不支持文件建立時間、文件上一次訪問時間的文件系統,time_create和time_access爲-1。

 

_MAX_PATH在stdlib.h中被定義爲260。

 

通常_finddata_t被定義爲_finddata32_t/_finddata64i32_t,_wfinddata_t被定義爲_wfinddata32_t/_wfinddata64i32_t。爲方便,下文中將_finddata_t和_wfinddata_t統稱爲_finddata_t。

 

文件屬性常量

 

一個文件/目錄能夠有多種屬性,每種屬性能夠是下面列出的屬性之一。

 

_A_ARCH

 

檔案。文件被BACKUP指令改變或清除時被設置。值:0x20。

 

_A_HIDDEN

 

隱藏。使用DIR指令通常看不到,除非使用/AH選項。值:0x02。

 

_A_NORMAL

 

普通。文件沒有更多屬性被設置,能夠沒有限制地被讀或寫。值:0x00。

 

_A_RDONLY

 

只讀。不能以「寫」爲目的打開該文件,而且不能建立同名的文件。值:0x01。

 

_A_SUBDIR

 

子目錄。值:0x10。

 

_A_SYSTEM

 

系統文件。使用DIR指令通常看不見,除非使用/A或/A:S選項。值:0x04。

 

要檢查x是否含有某個屬性a,能夠用x & a進行檢查。指定多個屬性可使用按位or運算符,例如_A_SYSTEM |  _A_RDONLY | _A_HIDDEN。

 

通配符(wildcards)

 

遍歷文件目錄時須要使用通配符,詳見個人另外一篇文章

 

_findfirst()/_findnext()/_findclose()函數

 

_findfirst()函數

 

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

 

實際上_findfirst()有10個版本,這裏只列出一個。

 

filespec

 

const char */const wchar_t *類型,目標文件說明(可包含通配符)。

 

fileinfo

 

_finddata_t *類型,函數將會填入文件/目錄信息。

 

返回值

 

若是成功,返回一個惟一的搜索句柄標識一個或一組和filespec說明匹配的文件,能夠用於接下來的_findnext()和_findclose()函數。不然_findfirst()返回-1。注意,intptr_t並非指針類型,只是int或__int64的typedef。

 

_findnext()函數

 

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

 

handle

 

intptr_t類型,搜索句柄。

 

fileinfo

 

_finddata_t *類型,函數將會填入文件/目錄信息。

 

返回值

 

若是成功,返回0,不然返回-1。若是沒有更多可以找到的文件了,也會致使失敗。

 

_findclose()函數

 

int _findclose(
    intptr_t handle
);

 

關閉搜索句柄並釋放相應的資源。

 

handle

 

搜索句柄。

 

返回值

 

成功返回0,失敗返回-1。

 

程序代碼

 

1. 遍歷目錄下的全部文件

 

#include <iostream>
#include <cstring>        // for strcat()
#include <io.h>
using namespace std;

void listFiles(const char * dir);

int main()
{
    char dir[200];
    cout << "Enter a directory (ends with \'\\\'): ";
    cin.getline(dir, 200);

    strcat(dir, "*.*");        // 在要遍歷的目錄後加上通配符
    listFiles(dir);

    return 0;
}

void listFiles(const char * dir)
{
    intptr_t handle;
    _finddata_t findData;

    handle = _findfirst(dir, &findData);    // 查找目錄中的第一個文件
    if (handle == -1)
    {
        cout << "Failed to find first file!\n";
        return;
    }

    do
    {
        if (findData.attrib & _A_SUBDIR
            && strcmp(findData.name, ".") == 0
            && strcmp(findData.name, "..") == 0
            )    // 是不是子目錄而且不爲"."或".."
            cout << findData.name << "\t<dir>\n";
        else
            cout << findData.name << "\t" << findData.size << endl;
    } while (_findnext(handle, &findData) == 0);    // 查找目錄中的下一個文件

    cout << "Done!\n";
    _findclose(handle);    // 關閉搜索句柄
}

 

程序遍歷目錄下的全部文件/目錄,若是是文件則輸出文件大小。

 

注意_findnext()函數成功返回0,所以要加上==0或!=-1進行判斷,不能省略。

 

此外還有一個值得注意的地方:

 

if (findData.attrib & _A_SUBDIR
    && strcmp(findData.name, ".")
    && strcmp(findData.name, "..")
)
...

 

使用_findfirst()、_findnext()進行搜索時,可能會獲得"."和".."兩個文件夾名。這兩個值能夠忽略。

 

2. 遍歷目錄中的全部文件

 

注意是「目錄中」而不是「目錄下」,這個程序將會遍歷一個目錄裏包含的全部文件。

 

#include <iostream>
#include <cstring>        // for strcpy(), strcat()
#include <io.h>

using namespace std;

void listFiles(const char * dir);

int main()
{
    char dir[200];
    cout << "Enter a directory: ";
    cin.getline(dir, 200);

    listFiles(dir);

    return 0;
}

void listFiles(const char * dir)
{
    char dirNew[200];
    strcpy(dirNew, dir);
    strcat(dirNew, "\\*.*");    // 在目錄後面加上"\\*.*"進行第一次搜索

    intptr_t handle;
    _finddata_t findData;

    handle = _findfirst(dirNew, &findData);
    if (handle == -1)        // 檢查是否成功
        return;

    do
    {
        if (findData.attrib & _A_SUBDIR)
        {
            if (strcmp(findData.name, ".") == 0 || strcmp(findData.name, "..") == 0)
                continue;

            cout << findData.name << "\t<dir>\n";

            // 在目錄後面加上"\\"和搜索到的目錄名進行下一次搜索
            strcpy(dirNew, dir);
            strcat(dirNew, "\\");
            strcat(dirNew, findData.name);

            listFiles(dirNew);
        }
        else
            cout << findData.name << "\t" << findData.size << " bytes.\n";
    } while (_findnext(handle, &findData) == 0);

    _findclose(handle);    // 關閉搜索句柄
}
相關文章
相關標籤/搜索