递归读取文件夹

白水晶大约 3 分钟Windows文件操作文件夹文件属性Windows C

C语言 Windows递归读取文件夹

题目要求

  • 递归枚举c:\windows\system32文件夹下的所有文件
  • 列出文件名称,全路径,以及文件大小和创建日期到日志文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

#define LOG_FILE "fileLog.txt"
#define MAX_TIME_STRING 256
#define DEST_FILE_PATH "C:Windows/System32/"

void findFiles(const char* path, FILE* logFile);
DWORD showFileTime(_In_ PFILETIME lptime, _Out_ char *timeString);
DWORD ShowFileSize(_In_ DWORD dwFileSizeHigh, _In_ DWORD dwFileSizeLow, _Out_ ULONGLONG & fileSize);

int main(int argc, char *argv[])
{   
    FILE* fp = NULL;
    fopen_s(&fp, LOG_FILE, "w");
    if (fp == NULL) {
        printf("无法打开日志文件:%s\n", LOG_FILE);
        return -1;
    }
    
    findFiles(DEST_FILE_PATH, fp);
    
    fclose(fp);
    fp = NULL;
    system("pause");
    return 0;
}

void findFiles(const char* path, FILE* logFile)
{
    static int depth = 0;               // 递归深度,用于输出目录名称缩进
    WIN32_FIND_DATAA findData;          // 当前文件或目录结构体
    HANDLE hFind = NULL;                // 查找到的句柄
    char subPath[MAX_PATH];             // 子路径,用于递归

    // 构造查询条件
    snprintf(subPath, sizeof(subPath), "%s*", path);
    

    // 开始查找
    hFind = FindFirstFileA(subPath, &findData);
    if (INVALID_HANDLE_VALUE == hFind) 
    {
        return;
    }

    do {
        // 排除"."与".."目录
        if (strcmp(findData.cFileName, ".") == 0 || strcmp(findData.cFileName, "..") == 0) 
            continue;
        // 构造完整路径 注意必须加上
        snprintf(subPath, sizeof(subPath), "%s/%s/", path, findData.cFileName);	
        
        // 判断是否是目录
        if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
        {
            // 输出目录名称并递归查找
            printf("%*s目录:%s\n", depth * 4, "", subPath);
            // 写入文件日志
            fprintf(logFile, "%*s目录:%s\n", depth * 4, "", subPath);
            depth++;
            findFiles(subPath, logFile);
            depth--;
        }  
        else 
        {
            
            char timeString[MAX_TIME_STRING];
            showFileTime(&(findData.ftCreationTime), timeString);
            ULONGLONG fileSize = 0;
            ShowFileSize(findData.nFileSizeHigh, findData.nFileSizeLow, fileSize);

            // 输出文件信息
            printf("%*s[文件:%s]\t\t文件大小:%lld\t\t字节\t\t\t文件创建时间:%s\n",
                4 * depth, "", subPath, fileSize, timeString);
            
            
            // 写入文件日志
            fprintf(logFile, "%*s[文件:%s]\t\t[文件大小:%lld字节]\t\t[文件创建时间:%s]\n",
                4 * depth, "", subPath, fileSize, timeString);
        }
    } while (FindNextFileA(hFind, &findData));

    // 关闭句柄
    FindClose(hFind);
}


//此代码使用 FindFirstFile() 和 FindNextFile() 来查找文件和目录,使用 fprintf() 来将文件路径、大小和创建日期写入日志文件,
//并使用递归调用 findFiles() 函数来遍历并记录目录下的子文件和子目录。为了美化输出,代码使用了递归深度来缩进显示目录名称,
//输出的目录名称与文件名称通过前缀字符("  目录:" 或 "  文件:")区分开来。


/*
*功能:转换文件时间并打印
*参数:PFILETIMR lptime 指向文件的时间的指针
*返回值:0
**********************/
DWORD showFileTime(_In_ PFILETIME lptime, _Out_ char* timeString)
{
    FILETIME ftLocal;   //文件时间结构
    SYSTEMTIME st;      //系统时间结构

    FileTimeToLocalFileTime(lptime,&ftLocal);       //调整为系统所在时区的时间
    FileTimeToSystemTime(&ftLocal, &st);            //将文件时间转换为SYSTEMTIME格式,便于显示

    //显示时间信息字符串
    //printf("%4d年%#02d月%#02d日,%#02d:%#02d:%#02d\n",
    //    st.wYear,
    //    st.wMonth,
    //    st.wDay,
    //    st.wHour,
    //    st.wMinute,
    //    st.wSecond
    //);
    sprintf_s(timeString, MAX_TIME_STRING, "%4d年%#02d月%#02d日,%#02d:%#02d:%#02d",
        st.wYear,
        st.wMonth,
        st.wDay,
        st.wHour,
        st.wMinute,
        st.wSecond
    );
    return 0;
}

/*
*功能:打印文件大小信息
*参数:DWORD dwFileSizeHigh,文件大小高32位
*      DWORD dwFileSizeLow ,文件大小低32位
**********************************/
DWORD ShowFileSize(_In_ DWORD dwFileSizeHigh, _In_ DWORD dwFileSizeLow, _Out_ ULONGLONG & fileSize)
{
    ULONGLONG liFileSize;
    liFileSize = dwFileSizeHigh;
    //移动到32位
    liFileSize <<= sizeof(DWORD) * 8;
    liFileSize += dwFileSizeLow;
    /*printf("文件大小:\t%I64u字节\n", liFileSize);*/
    fileSize = liFileSize;
    return 0;
}

上次编辑于:
贡献者: wucq@infogo