更新時間:2017-11-16 來源:黑馬程序員 瀏覽量:
1. linux提供opendir、readdir(readdir_r)、closedir和scandir等接口實現(xiàn)對目錄的讀取。
2. readdir返回指向下一個目錄項的指針,如果要自己傳入緩沖區(qū)存儲目錄項,應使用readdir_r代替。readdir的結(jié)果中包含當前目錄和上一級目錄的目錄項信息。
3. 在遍歷過程中,進程的工作目錄不會改變,在遞歸遍歷的時候,需要改變工作目錄(chdir)以識別相對路徑,或者每次都限定全局路徑。
4. 深度優(yōu)先遍歷目錄樹采用遞歸實現(xiàn)易編碼(參見如下代碼),廣度優(yōu)先遍歷則需借助隊列實現(xiàn)。當目錄下的文件數(shù)量較少時,采用廣度優(yōu)先遍歷效率會更高,因目錄下的目錄項基本都是連續(xù)存放,減少了很多磁盤尋道;而采用深度優(yōu)先遍歷,結(jié)果的聚合性更高。
1. int dir_traverse(const char *dir_name)
2. {
3. DIR *dirp = opendir(dir_name);
4. if(!dirp) {
5. perror("opendir");
6. return -1;
7. }
8.
9. struct stat st;
10. struct dirent *dir;
11. char fullpath[FILENM_MAX];
12. while((dir = readdir(dirp)) != NULL) {
13. if(!strcmp(dir->d_name, ".") || // 考慮當前目錄和上級目錄,否則會死循環(huán)
14. !strcmp(dir->d_name, "..")) {
15. continue;
16. }
17.
18. sprintf(fullpath, "%s/%s", dir_name, dir->d_name); //獲取全局路徑
19. printf("%s\n", fullpath); // 打印路徑
20. if(lstat(fullpath, &st) < 0) {
21. perror("lstat");
22. continue;
23. }
24. if(S_ISDIR(st.st_mode)) {
25. dir_traverse(fullpath); // 遞歸遍歷子目錄
26. }
27.
28. }
29.
30. closedir(dirp);
31.
32. return 0;
33. }
訪問目錄下某個文件時,需要逐個讀取目錄數(shù)據(jù)中的目錄項并與目標進行匹配獲得文件的inode號,假設文件的平均長度為10byte,加上inode、type及reclen等信息,每個目錄項的平均長度為16byte,假設采用4K的數(shù)據(jù)塊,則一個塊可以存放256個目錄項,按照ext2文件數(shù)據(jù)索引的方式,當目錄下文件數(shù)n少于256*12時,則在目錄下查找文件最多需要訪問n/256(向上取整)個數(shù)據(jù)塊,當目錄下文件數(shù)更多的時候,需要訪問的塊數(shù)會更快的增加(后面得到存儲數(shù)據(jù)的物理塊號需要多級索引),這也是在目錄下不應放太多文件的原因,如果將擁有很多文件的目錄均分成多個子目錄,多一級目錄會多一次(或多次,具體依賴于子目錄下文件數(shù)量)磁盤塊訪問,但在子目錄中查找文件的磁盤訪問開銷會小很多。
友情提示:獲得更多學科學習視頻+資料+源碼,請加QQ:3276250747。
本文版權(quán)歸黑馬程序員C/C++學院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明作者出處。謝謝!
作者:黑馬程序員C/C++培訓學院
首發(fā):http://c.itheima.com/