嵌入式 - linux软件编程: 目录 IO及时间相关的函数接口
目录
一、目录 IO
1. 操作方式:
2. 函数接口:
1. opendir
2. closedir
3. readdir
4. getcwd
5. chdir
6. mkdir
7. rmdir
3. 文件名和路径:
4.深度优先遍历
5.广度优先遍历
二、时间相关的函数接口
1. 时间类型分类:
2. 函数接口:
1. time
2. localtime
3. mktime
4. ctime
(补充)掩码:
一、目录 IO
1. 操作方式:
- 打开目录文件
- 读取目录文件中的目录项
- 关闭目录文件
2. 函数接口:
1. opendir
原型: DIR *opendir(const char *name);
功能: 打开目录流获得目录流指针
参数: name: 目录文件的路径
返回值: 成功返回目录流指针 失败返回NULL
#include "../head.h"int main(void)
{DIR *dp = NULL;struct dirent *pp = NULL;char filepath[256] = {0};printf("请输入路径:\n");m_fgets(filepath);dp = opendir(filepath);if (NULL == dp){perror("fail to opendir");return -1;}while (1){pp = readdir(dp);if (NULL == pp){break;}if ('.' == pp->d_name[0]){continue;}switch (pp->d_type){case DT_BLK:printf("块设备文件");break;case DT_CHR:printf("字符设备文件");break;case DT_DIR:printf("目录文件");break;case DT_FIFO:printf("管道文件");break;case DT_LNK:printf("链接文件");break;case DT_REG:printf("普通文件");break;case DT_SOCK:printf("套接字文件");break;}printf("\t\t%s\t\t%s/%s\n", pp->d_name, filepath, pp->d_name);}closedir(dp);return 0;
}
2. closedir
原型: int closedir(DIR *dirp);
功能: 关闭目录流指针
3. readdir
原型: struct dirent *readdir(DIR *dirp);
功能: 读取并返回下一个目录项的信息
参数: dirp: 目录流指针
返回值: 成功返回包含目录项信息的结构体指针 失败返回NULL 读到文件末尾返回NULL struct dirent { ino_t d_ino; /* Inode number: 通过inode找到文件对应的磁盘空间位置 */ off_t d_off; /* Not an offset; see below */ 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];/* Null-terminated filename: 文件名 */
};
4. getcwd
原型: char *getcwd(char *buf, size_t size);
功能: 获得当前工作目录的绝对路径
参数: buf: 存放路径字符串的空间首地址 size: 最多存放字符串的大小
返回值: 成功返回包含字符串空间的首地址 失败返回NULL
#include "../head.h"int main(void)
{char tmpbuffer[4096] = {0};FILE *fp = NULL;getcwd(tmpbuffer,sizeof(tmpbuffer));printf("当前路径:%s\n",tmpbuffer);mkdir("tmp",0777);rmdir("tmp");chdir("..");//上一级目录getcwd(tmpbuffer,sizeof(tmpbuffer));printf("当前路径:%s\n",tmpbuffer);fclose(fopen("file.txt","w"));return 0;
}
5. chdir
原型: int chdir(const char *path);
功能: 切换当前的工作路径
参数: path: 要切换的路径
返回值: 成功返回0 失败返回-1
6. mkdir
原型: int mkdir(const char *pathname, mode_t mode);
功能: 创建目录文件
注意:
- `r`: 读权限,决定用户是否能够查看目录下所有文件名
- `w`: 写权限,决定用户是否能够在目录下新建文件
- `x`: 执行权限,决定用户是否能够进入目录
7. rmdir
原型: int rmdir(const char *pathname);
功能: 删除目录文件
3. 文件名和路径:
file.txt
: 文件名./file.txt
: 路径
4.深度优先遍历
#include"../head.h"//=======深度优先遍历========//void listdir(char *dirpath)
{DIR *dp = NULL; // 目录流指针,表示打开的目录struct dirent *pp = NULL; // 目录项结构体指针,存储单个文件/目录的信息char tmpbuff[4096] = {0}; // 缓冲区,用于拼接完整路径(如"父目录/子文件")dp = opendir(dirpath); // 打开dirpath指定的目录if (NULL == dp) // 判断目录是否打开成功{perror("fail to opendir"); // 打印错误原因(如权限不足、目录不存在)printf("failed:%s\n", dirpath); // 打印打开失败的目录路径return; // 打开失败则退出当前函数}while(1){pp = readdir(dp); // 从打开的目录流中读取下一个目录项(文件或子目录)if (NULL == pp) // 若读取到目录末尾(无更多项),退出循环{break;}if ('.' == pp->d_name[0]) // 判断文件名是否以"."开头{continue; // 跳过隐藏文件/目录(Linux中以"."开头的为隐藏项)}//spritf 输出到数组里面sprintf(tmpbuff, "%s/%s", dirpath, pp->d_name); // 拼接路径:父目录 + "/" + 子项名称printf("%s\n", tmpbuff); // 打印完整路径if(pp->d_type == DT_DIR){listdir(tmpbuff);}}closedir(dp);return;
}int main(void)
{listdir("/home/linux");return 0;
}
5.广度优先遍历
#include "../head.h"
#include "linkqueue.h"/*** @brief 广度优先遍历指定目录下的所有文件和子目录* @param dirpath: 要遍历的目录路径* @note 采用队列实现广度优先搜索(BFS),先遍历当前目录,再遍历子目录*/
void listdir(char *dirpath)
{linknode *plinkqueue = NULL; // 链表队列指针(用于存储待遍历的目录路径)char tmppath[256] = {0}; // 临时存储从队列中取出的目录路径char filepath[1024] = {0}; // 存储拼接后的完整文件/目录路径DIR *dp = NULL; // 目录流指针(用于打开目录)struct dirent *pp = NULL; // 目录项结构体指针(用于读取目录中的内容)// 1. 创建空的链表队列(用于管理待遍历的目录)plinkqueue = create_empty_linkqueue();// 2. 将初始目录路径入队(作为第一个待遍历的目录)enter_linkqueue(plinkqueue, dirpath);// 3. 循环处理队列中的目录:只要队列不为空,就继续遍历while (!is_empty_linkqueue(plinkqueue)){// 3.1 从队列中取出一个目录路径,存储到tmppathquit_linkqueue(plinkqueue, tmppath);// 3.2 打开该目录,获取目录流指针dpdp = opendir(tmppath);if (NULL == dp) // 打开目录失败的处理{perror("fail to opendir"); // 打印错误信息(如权限不足、目录不存在等)printf("错误目录路径: %s\n", tmppath); // 打印失败的目录路径return; // 直接返回,终止遍历}// 3.3 循环读取当前目录下的所有目录项(文件或子目录)while (1){// 读取一个目录项,存储到pp中(NULL表示读取完毕)pp = readdir(dp);if (NULL == pp){break; // 目录项读取完毕,退出内层循环}// 跳过特殊目录(.表示当前目录,..表示父目录,避免无限循环)if ('.' == pp->d_name[0]){continue;}// 拼接完整路径:父目录路径 + "/" + 子项名称(文件或子目录)sprintf(filepath, "%s/%s", tmppath, pp->d_name);// 打印当前文件/目录的完整路径printf("%s\n", filepath);// 如果当前目录项是子目录(DT_DIR表示目录类型),则将其入队,等待后续遍历if (pp->d_type == DT_DIR){enter_linkqueue(plinkqueue, filepath);}}// 3.4 关闭当前目录的目录流(避免资源泄漏)closedir(dp);}// 4. 遍历结束后,销毁队列,释放内存destroy_linkqueue(&plinkqueue);return;
}/*** @brief 主函数:调用listdir函数遍历指定目录*/
int main(void)
{// 遍历"/home/linux"目录下的所有文件和子目录listdir("/home/linux");return 0;
}
二、时间相关的函数接口
1. 时间类型分类:
time_t
类型时间:- 1970-1-1 到现在的秒数
- 一般用于时间计算相关逻辑
struct tm
类型时间:- 包含年月日时分秒信息
char *
字符串类型时间:- 由时间拼接的字符串
2. 函数接口:
1. time
原型: time_t time(time_t *tloc);
功能: 返回1970-1-1 到现在的秒数
参数: 存放秒数空间的首地址
返回值: 成功返回秒数 失败返回-1
2. localtime
原型: struct tm *localtime(const time_t *timep);
功能: 将秒数转换为结构体时间
参数: timep: 1970-1-1 到现在的秒数
返回值: 成功返回包含时间的结构体指针 失败返回NULL struct tm { int tm_sec; /* Seconds (0-60) */ int tm_min; /* Minutes (0-59) */ int tm_hour; /* Hours (0-23) */ int tm_mday; /* Day of the month (1-31) */ int tm_mon; /* Month (0-11) */ int tm_year; /* Year - 1900 */ int tm_wday; /* Day of the week (0-6, Sunday = 0) */ int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */ int tm_isdst; /* Daylight saving time */
};
3. mktime
原型: time_t mktime(struct tm *tm);
功能: 将结构体时间转换为 `time_t` 类型的时间
参数: tm: 结构体时间的首地址
返回值: 成功返回 `time_t` 时间 失败返回-1
4. ctime
原型: char *ctime(const time_t *timep);
功能: 将 `time_t` 时间转换为字符串时间
#include "../head.h"int main(void)
{time_t t;time_t ret;struct tm *ptm = NULL;char *pstr = NULL;// time(&t); //等效于t = time(NULL);printf("t = %ld\n",t);ptm = localtime(&t);printf("%04d-%02d-%02d %02d:%02d:%02d\n",ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec);ret = mktime(ptm);printf("ret = %ld\n",ret);pstr = ctime(&ret);printf("pstr = %s\n",pstr);return 0;
}