使用 C 語言中的 opendir 函式

Jinku Hu 2023年1月30日 2021年2月28日
  1. 使用 opendir 函式開啟一個目錄流
  2. 使用 readdir 函式來遍歷目錄條目
使用 C 語言中的 opendir 函式

本文將介紹幾種在 C 語言中使用 opendir 函式的方法。

使用 opendir 函式開啟一個目錄流

opendir 函式是 POSIX 規範的一部分,在 <dirent.h> 標頭檔案中定義。該函式使用一個 char 指標引數來指定要開啟的目錄名。opendir 返回 DIR*結構,如果遇到錯誤則返回 NULL。DIR 資料型別是為了表示目錄流而實現的,但使用者不應該分配 DIR 型別的物件。在下面的示例程式碼中,我們從第一個命令列引數中獲取目錄名,並將其值傳遞給 opendir 函式。

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.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 迴圈,列印開啟的目錄流中的每個條目。我們修改了 opendirclosedir 函式呼叫周圍的程式碼,以檢查錯誤並輸出相應的資訊進行除錯。檢查庫函式是否成功返回總是好的、安全的做法。

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.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 <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.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);
}
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn

相關文章 - C File