C语言遍历文件夹(Windows下),读取文件信息至结构体,然后保存至文件

参考资料:
C语言遍历文件夹

首先首先根据参考资料中文章理解遍历文件夹的方法。

#include <stdio.h>
#include <string.h>
#include <dirent.h> 

void myfilerecursive(char *path);


int main()
{
    // 文件夹名称
    char name[100000] = "D:\\test"; 
    // printf("Enter path to list files: ");
    // scanf("%s", name);

    myfilerecursive(name);

    return 0;
}

void myfilerecursive(char *basePath)
{
	// 路径
    char path[1000];
    struct dirent *dp;
    DIR *dir = opendir(basePath);

   	// 如果是文件则直接结束此次调用
    if (!dir) {
        return;
    }

    while ((dp = readdir(dir)) != NULL)
    {
    	// 跳过 "." 和 ”..“
        if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)
        {
        	// 将文件名和路径进行拼接形成一个完整路径
            printf("%s\n", dp->d_name);
            strcpy(path, basePath);
            strcat(path, "/");
            strcat(path, dp->d_name);
			// 递归遍历
            myfilerecursive(path);
        }
    }
    closedir(dir);
}

这是 结构体 dirent 的结构,通过访问这个结构体中数据可以获取文件名
结构体 dirent 的结构

进阶

题目描述
     遍历一个文件夹,将遍历得到的信息(文件名、文件类型、文件大小等)保存至结构体中,然后再把结构体中的信息保存至一个文件中。

代码
对于代码的理解请看注释

#include <stdio.h>
#include <string.h>
#include <dirent.h>

void myfilerecursive(char *path, struct FILE_STR *fileStrs);
int get_file_size(char *filePath);
char* get_suffix(char* dest, char* filename);
char *right(char *dest, char *src, int n);

// 文件信息结构体
// 注意:结构中应当使用数组而不是指针,否则写入文件时无法正确获取指针的结束位
typedef struct FILE_STR{
    char filename[100]; // 文件名
    char fileType[10];   // 文件类型(文件夹或文件)
    int fileSize;   // 文件大小
    char suffix[10];    // 文件后缀
} file_str;

// 全局变量,记录结构体数量(或者使用指针作为参数代替)
int count = 0;

int main() {

    char name[10000];
    // printf("Enter path to list files: ");
    // scanf("%s", name);

    // myfilerecursive(name);
    char basePath[100] = "F:\\tmp";
    file_str fileStrs[100];
    // 递归遍历文件夹,并将信息保存至结构体数组中
    myfilerecursive(basePath, fileStrs);
    
    // 定义一个文件指针
    FILE *fp ;
    // 打开文件,没有文件自动创建
    if((fp=fopen("files.txt","w"))==NULL) {
        perror("fopen");
        printf("====error====");
    }
    int i = 0;
    // 将结构体数组中的信息保存至文件中
    while (i < count){
        // 写入数据至文件中  (注意:如果其他步骤除了问题(虽然没有报错),这一步基本也不会成功,可以把这个放在循环外,看看是否有问题)
        fprintf(fp,"filename:%s \tfileType:%s \tfileSize:%d \tsuffix:%s\n", fileStrs[i].filename, 
            fileStrs[i].fileType, fileStrs[i].fileSize, fileStrs[i].suffix);
        i++;
    }
    // 必须要关闭,否则内容不会写入文件中
    fclose(fp);
    return 0;
}

void myfilerecursive(char *basePath, file_str *fileStrs) {
    // path 作为一个目录,记录当前访问的目录
    char path[1000];
    // 定义结构体数组(指针)
    struct dirent *dp;
    DIR *dir = opendir(basePath);
    // if (!dir) {
    //     return; 
    // }
    // 以上写法等同于
    if (dir == NULL) {
        // 如果该路径(path)不可读,则直接结束此次方法调用
        return;
    }
    while ((dp = readdir(dir)) != NULL) {
        // 不读取 "." 和 ".."
        if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)
        {
            // 定义结构体
            file_str fileStr;
            strcpy(fileStr.filename, dp->d_name); // fileStr.filename = dp->d_name; 指针写法在将信息写入文件时有问题
            // 复制 basePath 至 path
            strcpy(path, basePath);
            // 将 / 追加到 path 中,拼接为一个目录
            strcat(path, "/");
            // 将文件名或目录名(d_name)追加到 path 中
            strcat(path, dp->d_name);
            // 判断是否是文件夹
            DIR *isDir = opendir(path);
            int size = get_file_size(path);
            if (isDir != NULL) {
                // warning: ISO C++ forbids converting a string constant to 'char*'
                char tmp[10] = "文件夹";
                strcpy(fileStr.fileType, tmp); // fileStr.fileType = tmp;
            } else {
                fileStr.fileSize = size;
                char tmp[10] = "文件";
                strcpy(fileStr.fileType, tmp); // fileStr.fileType = tmp;
                
                char suf[10];
                get_suffix(suf, dp->d_name);
                strcpy(fileStr.suffix, suf); // fileStr.suffix = suf;
            }
            // fileStr.filename = dp->d_name;
            fileStrs[count++] = fileStr;
            // 递归调用
            myfilerecursive(path, fileStrs);
        }
    }
    closedir(dir);
}

// 获取文件大小
int get_file_size(char* filePath)
{
    FILE *fp=fopen(filePath,"r");
    if(!fp) {
        return -1;
    }
    fseek(fp,0L,SEEK_END);
    int size=ftell(fp);
    fclose(fp);
    
    return size;
}

// 获取文件名后缀
char* get_suffix(char* dest, char* filename) {
    // 注意:strlen()函数得到英文和中文字符的长度不一样
    int len = strlen(filename);
    int i;
    for (i = len - 1; i >= 0; i--) {
        // 最后一次出现字符 '.' 的位置
        if (filename[i] == '.') {
            right(dest, filename, len - i - 1);
            break;
        }
    }
    return dest;
}

// 从右边开始截取指定数量字符串
char *right(char *dest, char *src, int n) {
    char *p = dest;
    char *q = src;
    int len = strlen(src);

    if (n > len) {
        n = len;
    }
    //int start=len-n;
    //q=q+start;
    q += len - n;
    while (n--) {
        *(p++) = *(q++);    
    }
    *(p++) = '\0';
    return dest;
}

遍历文件夹的目录结构:
在这里插入图片描述

最终保存文件结果:
结果


版权声明:本文为qq_38431321原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。