C语言实现Windows7下的文件清单生成器

来源:互联网 发布:抑毛液有用吗 知乎 编辑:程序博客网 时间:2024/06/01 23:42
一、引子
朋友提出这样一个需求:快速获得某个文件夹(及其子文件夹)内全部的文件名。
事情的起因是这样的,他正在按公司的要求整理一个项目的佐证材料,按照不同的检查项,应把相关材料放在不同的文件夹中。但是最终还是需要一份所有材料的清单。由于佐证材料经常需要更新和变动,他想要一种简单的方法快速获得这份清单(记录每个文件夹下的所有文件名)。

二、思路分析
(一)我最初想到的方法是直接在DOS模式下找到相应文件夹,然后输入:
dir /s >filesout.txt
生成的结果如下:


虽然所有文件和文件夹都很清晰地显示出来,但并未达到朋友的要求。主要是因为:
1. 上图的输出是先把一个层级内的全部文件和文件夹都输出,然后再把每个文件夹内下一层级的内容逐次输出。朋友希望像树形展开图那样地直观体现文件层级。 
2. 存在.和..这样无意义的文件夹信息,而且日期、文件大小并不是朋友想要的信息。

(二)采用编程实现
A. 程序逻辑:很简单,就是一个递归。
1. 给定起始目录
2. 递归函数
    首先判断输入的文件名是文件还是文件夹
        2.1 若为文件,则输出文件名
        2.2 若为文件夹,则首先输出文件夹名,并将该文件夹名作为参数,递归调用本身这个函数

B. 实现过程中遇到的问题
1. 计划利用C语言完成,但很快就发现,虽然C语言提供了读文件和写文件的函数,但并不提供文件夹管理之类的函数,因为这些函数是操作系统相关的!由于计划在Windows7下使用,索引必须查找Windows API,具体可以参考: 
https://msdn.microsoft.com/en-us/library/windows/desktop/ff818516(v=vs.85).aspx
针对文件和文件夹查找,Windows API给出以下两个函数:FindFirstFile、FindNextFile
2. 使用Windows API,需要#include <windows.h>,好在PosPro目前使用的是Codeblocks IDE,自带了这个头文件,省去了不少麻烦。
3. 为了实现傻瓜式操作,朋友要求把exe文件放到需要生成清单的文件夹下,双击运行,生成一个记录文件清单的TXT文件。所以需要GetCurrentDirectory函数来获得当前路径。
4. 特别提示,对于FileFirstFile函数,要提供绝对路径,并且在最后要增加“\*”,否则搜索可能无法获得正常结果

三、程序实现
源代码如下:
/*2016.10.18 by PosPro功能:    按照文件夹层级输出当前文件夹下全部文件名信息,    以<>表示文件夹名    生成结果保存在当前目录的_IndexOut.txt文件中使用方法:    把exe文件放到需生成清单的文件夹下,双击运行即可*/#include <stdlib.h>#include <stdio.h>#include <windows.h>#include <tchar.h>FILE *outfile;  //一个全局变量,以便各层递归都可以直接使用void printFileMap(TCHAR *fn, int level);  //递归函数void main(){    outfile=fopen("_IndexOut.txt","w");  //最终结果保存在此文件中    TCHAR szBuf[MAX_PATH]; //存储当前路径    GetCurrentDirectory(MAX_PATH, szBuf);    _tcscat(szBuf,_T("\\")); //上句中获得的路径不包括(\),这里加上    printf("请稍候,工作完成后本对话框会自动关闭\n"); //在DOS提示框中输出的信息    printf("生成结果见当前目录下新生成的文件: _IndexOut.txt\n");    printf("WORKING...Please Wait...\n");    printFileMap(szBuf, 0); //启动递归函数    fprintf(outfile, "\n\n\n===Programmed By PosPro 2016.10.18=======\n");    fprintf(outfile, "========Thanks for using=================\n");    fclose(outfile);}void printFileMap(TCHAR* fn, int level){    WIN32_FIND_DATA FindFileData, nextFileData;  //以此结构体保存文件信息    HANDLE hFind;    TCHAR searchFilePath[MAX_PATH];    _tcscpy(searchFilePath, fn);    _tcscat(searchFilePath, _T("*")); //必须在搜索路径后加入通配符(*), FindFirstFile才能正常运行    hFind=FindFirstFile(searchFilePath, &FindFileData);    if (hFind != INVALID_HANDLE_VALUE){ //如果为空文件夹,或者文件不存在,则不进入        do{            if(FindFileData.dwFileAttributes!=FILE_ATTRIBUTE_DIRECTORY){ //如果为文件,则打印文件名                int i;                for(i=level; i>0; i--)  //根据不同层级,打印空格以错开位置                    fprintf(outfile,"  ");                fprintf(outfile, "%s\n",FindFileData.cFileName);            }            else{                if(_tcscmp(FindFileData.cFileName,_T("."))&&_tcscmp(FindFileData.cFileName,_T("..")))                //实现对.和..这两个文件夹的过滤                {                    TCHAR nextf[MAX_PATH];                    int i;                    for(i=level; i>0; i--)                        fprintf(outfile, "  ");                    fprintf(outfile, "<%s>\n",FindFileData.cFileName);                    //必须构建出绝对路径,才能做下一步搜索!                    _tcscpy(nextf, fn);                    _tcscat(nextf, FindFileData.cFileName);                    _tcscat(nextf,_T("\\"));                    printFileMap(nextf, level+1);                }             }        }while(FindNextFile(hFind, &FindFileData));    }    FindClose(hFind);}

最后生成清单示例:



本文在:http://www.cnblogs.com/pospro 上同步发布

0 0
原创粉丝点击