本文可轉載,轉載請註明出處:http://www.cnblogs.com/collectionne/p/6815924.html。html
前面的一篇文章咱們講了用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); // 關閉搜索句柄 }