使用 C 語言中的 opendir 函式
Jinku Hu
2023年10月12日
本文將介紹幾種在 C 語言中使用 opendir
函式的方法。
使用 opendir
函式開啟一個目錄流
opendir
函式是 POSIX 規範的一部分,在 <dirent.h>
標頭檔案中定義。該函式使用一個 char
指標引數來指定要開啟的目錄名。opendir
返回 DIR*
結構,如果遇到錯誤則返回 NULL。DIR
資料型別是為了表示目錄流而實現的,但使用者不應該分配 DIR
型別的物件。在下面的示例程式碼中,我們從第一個命令列引數中獲取目錄名,並將其值傳遞給 opendir
函式。
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
DIR *dp;
struct dirent *dirp;
if (argc != 2) {
fprintf(stderr, "Usage: ./program directory_name\n");
exit(EXIT_FAILURE);
}
dp = opendir(argv[1]);
while ((dirp = readdir(dp)) != NULL) printf("%s\n", dirp->d_name);
closedir(dp);
exit(EXIT_SUCCESS);
}
使用 readdir
函式來遍歷目錄條目
一旦目錄流開啟,我們檢索到有效的 DIR*
,我們就可以使用 readdir
函式讀取其中的每個條目。每次呼叫 readdir
函式都會返回一個指向 dirent
結構的指標,代表下一個目錄條目。當到達目錄流的終點時,readdir
返回 NULL
。因此,我們實現了一個簡單的 while
迴圈,列印開啟的目錄流中的每個條目。我們修改了 opendir
和 closedir
函式呼叫周圍的程式碼,以檢查錯誤並輸出相應的資訊進行除錯。檢查庫函式是否成功返回總是好的、安全的做法。
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
DIR *dp;
struct dirent *dirp;
if (argc != 2) {
fprintf(stderr, "Usage: ./program directory_name\n");
exit(EXIT_FAILURE);
}
errno = 0;
if ((dp = opendir(argv[1])) == NULL) {
switch (errno) {
case EACCES:
printf("Permission denied\n");
break;
case ENOENT:
printf("Directory does not exist\n");
break;
case ENOTDIR:
printf("'%s' is not a directory\n", argv[1]);
break;
}
exit(EXIT_FAILURE);
}
while ((dirp = readdir(dp)) != NULL) printf("%s\n", dirp->d_name);
if (closedir(dp) == -1) perror("closedir");
exit(EXIT_SUCCESS);
}
另外,我們還可以為 readdir
函式增加一些查錯的條件語句,因為前面的例子可能會在目錄名無效或發生其他錯誤時產生不清晰的輸出。下面的程式碼會在遍歷成功後額外輸出目錄結束的達成狀態。
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
DIR *dp;
struct dirent *dirp;
if (argc != 2) {
fprintf(stderr, "Usage: ./program directory_name\n");
exit(EXIT_FAILURE);
}
errno = 0;
if ((dp = opendir(argv[1])) == NULL) {
switch (errno) {
case EACCES:
printf("Permission denied\n");
break;
case ENOENT:
printf("Directory does not exist\n");
break;
case ENOTDIR:
printf("'%s' is not a directory\n", argv[1]);
break;
}
exit(EXIT_FAILURE);
}
errno = 0;
while ((dirp = readdir(dp)) != NULL) printf("%s\n", dirp->d_name);
if (errno != 0) {
if (errno == EBADF)
printf("Invalid directory stream descriptor\n");
else
perror("readdir");
} else {
printf("End-of-directory reached\n");
}
if (closedir(dp) == -1) perror("closedir");
exit(EXIT_SUCCESS);
}
作者: Jinku Hu