
在嵌入式 Linux 应用开发中,opendir、readdir 和 closedir 函数是用于处理目录操作的重要函数,它们共同构成了遍历目录内容的基本工具。
opendir 函数#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);opendir 函数用于打开一个指定名称的目录,并返回一个指向 DIR 类型对象的指针。DIR 类型是一个不透明的数据类型,用于表示一个打开的目录流,后续的 readdir 和 closedir 函数将使用这个目录流来进行操作。
name:要打开的目录的路径名,可以是绝对路径或相对路径。DIR 类型对象的指针,该指针可用于后续的目录读取操作。NULL,并设置 errno 变量来指示具体的错误原因,常见的错误包括目录不存在、权限不足等。#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main() {
DIR *dir;
const char *dir_name = "/tmp";
dir = opendir(dir_name);
if (dir == NULL) {
perror("opendir");
return 1;
}
// 后续可以使用 dir 进行目录读取操作
// 关闭目录
closedir(dir);
return 0;
}二、readdir 函数#include <dirent.h>
struct dirent *readdir(DIR *dirp);readdir 函数用于从一个打开的目录流中读取下一个目录项,并返回一个指向 struct dirent 类型对象的指针。每次调用 readdir 函数,它都会返回目录中的下一个文件或子目录的信息,直到目录的末尾。
dirp:指向 DIR 类型对象的指针,该指针是通过 opendir 函数返回的。struct dirent 类型对象的指针,该对象包含了当前目录项的信息,如文件名、文件类型等。NULL,并且不会设置 errno 变量。NULL,并设置 errno 变量来指示具体的错误原因。struct dirent 结构体struct dirent 结构体定义了目录项的信息,常见的成员如下:
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* not an offset; see NOTES */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported by all filesystem types */
char d_name[256]; /* filename */
};d_ino:文件的索引节点号。d_type:文件的类型,常见的值包括 DT_REG(普通文件)、DT_DIR(目录)、DT_LNK(符号链接)等。d_name:文件名。#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main() {
DIR *dir;
struct dirent *entry;
const char *dir_name = "/tmp";
dir = opendir(dir_name);
if (dir == NULL) {
perror("opendir");
return 1;
}
while ((entry = readdir(dir)) != NULL) {
printf("File name: %s\n", entry->d_name);
}
closedir(dir);
return 0;
}三、closedir 函数#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);closedir 函数用于关闭一个之前通过 opendir 函数打开的目录流,并释放相关的资源。
dirp:指向 DIR 类型对象的指针,该指针是通过 opendir 函数返回的。errno 变量来指示具体的错误原因。#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main() {
DIR *dir;
const char *dir_name = "/tmp";
dir = opendir(dir_name);
if (dir == NULL) {
perror("opendir");
return 1;
}
// 进行目录读取操作
if (closedir(dir) == -1) {
perror("closedir");
return 1;
}
return 0;
}①查找特定文件或目录:在嵌入式系统中,有时需要查找特定名称或类型的文件或目录。可以使用 opendir 打开指定目录,readdir 遍历目录下的所有项,通过比较 struct dirent 结构体中的 d_name 和 d_type 成员来找到目标文件或目录。
示例代码:
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
int find_file(const char *dir_path, const char *file_name) {
DIR *dir = opendir(dir_path);
if (dir == NULL) {
perror("opendir");
return -1;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, file_name) == 0) {
closedir(dir);
return 0;
}
}
closedir(dir);
return -1;
}
int main() {
const char *dir_path = "/tmp";
const char *file_name = "test.txt";
if (find_file(dir_path, file_name) == 0) {
printf("File found!\n");
} else {
printf("File not found.\n");
}
return 0;
}②监控目录变化:嵌入式系统可能需要实时监控某个目录下的文件变化,如文件的创建、删除或修改。可以定期使用 opendir 和 readdir 遍历目录,记录文件列表,然后与上一次的记录进行比较,从而检测到目录的变化。
加载多个配置文件:在嵌入式系统中,可能存在多个配置文件存放在同一个目录下。可以使用 opendir 打开配置文件所在的目录,readdir 遍历目录下的所有文件,筛选出配置文件(如以 .conf 结尾的文件),然后依次加载这些配置文件。
示例代码:
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
void load_config_files(const char *config_dir) {
DIR *dir = opendir(config_dir);
if (dir == NULL) {
perror("opendir");
return;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (strstr(entry->d_name, ".conf") != NULL) {
char file_path[256];
snprintf(file_path, sizeof(file_path), "%s/%s", config_dir, entry->d_name);
// 加载配置文件的具体逻辑
printf("Loading config file: %s\n", file_path);
}
}
closedir(dir);
}
int main() {
const char *config_dir = "/etc/myapp/config";
load_config_files(config_dir);
return 0;
}清理过期日志文件:嵌入式系统通常会产生大量的日志文件,为了避免占用过多的存储空间,需要定期清理过期的日志文件。可以使用 opendir 打开日志文件所在的目录,readdir 遍历目录下的所有日志文件,根据文件的创建时间或修改时间判断文件是否过期,如果过期则删除该文件。
示例代码:
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
void clean_expired_logs(const char *log_dir, time_t expiration_time) {
DIR *dir = opendir(log_dir);
if (dir == NULL) {
perror("opendir");
return;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
char file_path[256];
snprintf(file_path, sizeof(file_path), "%s/%s", log_dir, entry->d_name);
struct stat file_stat;
if (stat(file_path, &file_stat) == 0) {
if (file_stat.st_mtime < expiration_time) {
if (unlink(file_path) == 0) {
printf("Deleted expired log file: %s\n", file_path);
} else {
perror("unlink");
}
}
}
}
closedir(dir);
}
int main() {
const char *log_dir = "/var/log/myapp";
time_t expiration_time = time(NULL) - 3600 * 24 * 7; // 过期时间为一周前
clean_expired_logs(log_dir, expiration_time);
return 0;
}播放列表生成:在嵌入式多媒体系统中,需要生成播放列表来管理媒体文件。可以使用 opendir 打开媒体文件所在的目录,readdir 遍历目录下的所有媒体文件(如 .mp3、.avi 等),将这些文件的路径添加到播放列表中。
示例代码:
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
void generate_playlist(const char *media_dir) {
DIR *dir = opendir(media_dir);
if (dir == NULL) {
perror("opendir");
return;
}
FILE *playlist_file = fopen("playlist.txt", "w");
if (playlist_file == NULL) {
perror("fopen");
closedir(dir);
return;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (strstr(entry->d_name, ".mp3") != NULL || strstr(entry->d_name, ".avi") != NULL) {
char file_path[256];
snprintf(file_path, sizeof(file_path), "%s/%s", media_dir, entry->d_name);
fprintf(playlist_file, "%s\n", file_path);
}
}
fclose(playlist_file);
closedir(dir);
}
int main() {
const char *media_dir = "/mnt/media";
generate_playlist(media_dir);
return 0;
}