C语言:如何得到指定地址的文件夹中所有文件的文件名和其修改时间 包括子文件内的

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言:如何得到指定地址的文件夹中所有文件的文件名和其修改时间 包括子文件内的相关的知识,希望对你有一定的参考价值。

因为我要得到所有文件名 然后用kmp算法模式匹配 再按时间排序 但是我不知道得到文件名和文件信息的语句
windows下

俺前段时间写了段功能相似的程序,但用的是用C++/STL写的,访问目录使用了win32 api(能访问指定目录的子目录)。

获取文件名与修改时间由FileOfDirectory::detectFiles实现(其实你只需要看这一个函数即可)。

这段程序以STL数组保存单个文件名,查询过程中没有回溯,wcsstr函数内部也是KMP,所以事实上这个程序也是按KMP查询的

安时间排序时使用STL算法库,时间复杂度同快速排序。

最后,这段代码是在VS2010编译的。

# include <vector>

# include <algorithm>

struct FileNameAndTime

wchar_t szPath[MAX_PATH];   //file directory

wchar_t szName[MAX_PATH];  //file name

FILETIME lastAcc;           //last access time

FileNameAndTime()

memset(&lastAcc, 0, sizeof(lastAcc));  

memset(szName, 0, sizeof(wchar_t) * MAX_PATH);

memset(szPath, 0, sizeof(wchar_t) * MAX_PATH);

FileNameAndTime(const PWCHAR fn, const PWCHAR pa, const LPFILETIME ft)

if( (0 == fn) || (0 == pa) || (0 == ft) )

return;

memcpy(&lastAcc, ft, sizeof(lastAcc));

wcscpy(szName, fn);

wcscpy(szPath, pa);

FileNameAndTime(const FileNameAndTime& fnd)

memcpy(&this->lastAcc, &fnd.lastAcc, sizeof(this->lastAcc));

wcscpy(this->szName, fnd.szName);

wcscpy(this->szPath, fnd.szPath);

const FileNameAndTime& operator=(const FileNameAndTime& fnd)

if(this != &fnd) 

memcpy(&this->lastAcc, &fnd.lastAcc, sizeof(this->lastAcc));

wcscpy(this->szName, fnd.szName);

wcscpy(this->szPath, fnd.szPath);

return *this;

void GetFullPath( wchar_t (&fp)[MAX_PATH] )  const

wcscpy(fp, szPath);

wcscat(fp, szName);

friend bool operator>(const FileNameAndTime& l, const FileNameAndTime& r);   //compare this object by access time

;

bool operator<(const FileNameAndTime& l, const FileNameAndTime& r)  //for sort

if(l.lastAcc.dwHighDateTime < r.lastAcc.dwHighDateTime)

return true;

else if (l.lastAcc.dwHighDateTime == r.lastAcc.dwHighDateTime)

if(l.lastAcc.dwLowDateTime < r.lastAcc.dwLowDateTime)

return true;

return false;

class FileOfDirectory

private:

static const wchar_t szDot[];

static const wchar_t szDotDot[];

static const wchar_t cStar;

static const wchar_t cSlash;

private:

std::vector<FileNameAndTime> vecFT;

wchar_t szCurrentPath[MAX_PATH];

private:

void validatePath(const wchar_t* pPath)

wcscpy(szCurrentPath, pPath);

int len = wcslen(szCurrentPath);

if( (cStar != szCurrentPath[len - 1])

&& (cSlash != szCurrentPath[len - 2]) )

szCurrentPath[len] = cSlash;

szCurrentPath[len + 1] = cStar;

szCurrentPath[len + 2] = 0;

return;

if( (cStar != szCurrentPath[len - 1])

&& (cSlash == szCurrentPath[len - 2]) )

szCurrentPath[len] = cStar;

szCurrentPath[len + 1] = 0;

return;

void detectFiles(const LPWSTR szDir)

WIN32_FIND_DATA ffd;  

HANDLE hFind = ::FindFirstFile(szDir, &ffd);

if (INVALID_HANDLE_VALUE == hFind) 

return ;

do

            if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)

if( (0 == wcscmp(ffd.cFileName, szDot)) || (0 == wcscmp(ffd.cFileName, szDotDot)))

continue; 

else  

wchar_t szTempPath[MAX_PATH];

wcscpy(szTempPath, szDir);

szTempPath[wcslen(szTempPath) - 1] = 0;

wcscat(szTempPath, ffd.cFileName);

int len = wcslen(szTempPath);

szTempPath[len] = cSlash;

szTempPath[len + 1] = cStar;

szTempPath[len + 2] = 0;

detectFiles(szTempPath);

else  

wchar_t path[MAX_PATH];

wcscpy(path, szDir);

path[wcslen(path) - 1] = 0;

vecFT.push_back(FileNameAndTime(ffd.cFileName,path, &ffd.ftLastAccessTime));

while (::FindNextFile(hFind, &ffd) != 0);

public:

FileOfDirectory(const LPWSTR szDir)

validatePath(szDir);

detectFiles(szCurrentPath);

void SortByAccessTime()

sort(vecFT.begin(), vecFT.end());

int NumOfFiles() const  return vecFT.size(); 

int FindFilesByKeyWord(wchar_t* pszFn, int* outCome, int outComeLen, bool bMatchAll = false)

wchar_t szTemp[MAX_PATH], szFnLwr[MAX_PATH];

int index = 0;

wcscpy(szFnLwr, pszFn);

_wcslwr(szFnLwr);

for(int i = 0; i < vecFT.size(); ++i)

wcscpy(szTemp, vecFT[i].szName);

_wcslwr(szTemp);

if(true == bMatchAll)

if(0 == wcscmp(szTemp, szFnLwr))

if(index >= outComeLen)

return index;

outCome[index++] = i;

else

if(0 != wcsstr(szTemp, szFnLwr))

if(index >= outComeLen)

return index;

outCome[index++] = i;

FileNameAndTime GetItemByID(int index)

if( (index >= 0) && (index < vecFT.size()) )

return FileNameAndTime(vecFT[index]);

;

const wchar_t FileOfDirectory::szDot[] = L".";

const wchar_t FileOfDirectory::szDotDot[] = L"..";

const wchar_t FileOfDirectory::cStar = L'*';

const wchar_t FileOfDirectory::cSlash = L'\\\\';

void __stdcall entp3()  //测试程序

FileOfDirectory fod(L"E:\\\\game");

int ids[256] =  0 ;

fod.SortByAccessTime();

int len = fod.FindFilesByKeyWord(L"main", ids, 256);

for(int i = 0; i <len; ++i) 

FileNameAndTime fnt(fod.GetItemByID(ids[i]));

CDbgString::OutputDbgStringW(L"\\r\\n%s%s", fnt.szPath, fnt.szName);

测试结果如图所示。

追问

我在vs2010下编译不了 为什么没有main主函数 还看不太懂class FileOfDirectory

追答

哦,俺也用的是vs2010,这个要设置一下才能不写main。
项目名-右键-属性-链接器-子系统:改为未设置
项目名-右键-属性-链接器-高级:输入entp3就能通过编译。
你也可以不改项目属性。
如果你写控制台程序,把entp3的代码写到main里即可,如果是windows程序,写到WinMain里即可。
当然你可以在自己的main函数中用FileOfDirectory类。

FileOfDirectory中:
validatePath用于修改路径的,比如你想枚举出c:\abc下所有的文件与文件夹,函数FindFirstFile要求你输入c:\abc\*才行。
detectFiles是得到目录下所有文件的,通过递归扫描子目录。
SortByAccessTime是按修改时间排序文件的,因为先搜索近期用过的文件意义比较大。
int FindFilesByKeyWord(wchar_t* pszFn, int* outCome, int outComeLen, bool bMatchAll = false)用于搜索指定文件,可以返回所有符合条件的文件名索引。pszFn是关键字,数组outCome用于存放搜索到的文件的索引,outComeLen是数组outCome的长度,bMatchAll = true表示必须和关键字全部匹配才能返回,反之只要文件名中包含关键就可返回。
GetItemByID更具索引返回FileNameAndTime 对象,一般和FindFilesByKeyWord配合使用。

参考技术A //获取指定目录下的所有文件列表 author:wangchangshaui jlu
char** getFileNameArray(const char *path, int* fileCount)

int count = 0;
char **fileNameList = NULL;
struct dirent* ent = NULL;
DIR *pDir;
char dir[512];
struct stat statbuf;

//打开目录
if ((pDir = opendir(path)) == NULL)

myLog("Cannot open directory:%s\n", path);
return NULL;

//读取目录
while ((ent = readdir(pDir)) != NULL)
//统计当前文件夹下有多少文件(不包括文件夹)
//得到读取文件的绝对路径名
snprintf(dir, 512, "%s/%s", path, ent->d_name);
//得到文件信息
lstat(dir, &statbuf);
//判断是目录还是文件
if (!S_ISDIR(statbuf.st_mode))

count++;

//while
//关闭目录
closedir(pDir);
// myLog("共%d个文件\n", count);

//开辟字符指针数组,用于下一步的开辟容纳文件名字符串的空间
if ((fileNameList = (char**) myMalloc(sizeof(char*) * count)) == NULL)

myLog("Malloc heap failed!\n");
return NULL;


//打开目录
if ((pDir = opendir(path)) == NULL)

myLog("Cannot open directory:%s\n", path);
return NULL;

//读取目录
int i;
for (i = 0; (ent = readdir(pDir)) != NULL && i < count;)

if (strlen(ent->d_name) <= 0)

continue;

//得到读取文件的绝对路径名
snprintf(dir, 512, "%s/%s", path, ent->d_name);
//得到文件信息
lstat(dir, &statbuf);
//判断是目录还是文件
if (!S_ISDIR(statbuf.st_mode))

if ((fileNameList[i] = (char*) myMalloc(strlen(ent->d_name) + 1))
== NULL)

myLog("Malloc heap failed!\n");
return NULL;

memset(fileNameList[i], 0, strlen(ent->d_name) + 1);
strcpy(fileNameList[i], ent->d_name);
myLog("第%d个文件:%s\n", i, ent->d_name);
i++;

//for
//关闭目录
closedir(pDir);

*fileCount = count;
return fileNameList;
参考技术B windows下和linux下可是有很大区别的噢。追问

windows下

易语言 如何 列出 指定目录下 所有 文件名

@ECHO OFF
FOR /F "tokens=1,2" %%a IN (city.txt) DO (
IF EXIST %%a% %.txt (
COPY %%a% %.txt %%b% %.txt
)
)

这是从别人那边转过来的。我不大懂这个东西。
以下内容来自
dir /a/b 指定目录路径 >输出目录路径\1.txt

如果输出路径为%ComputerName%.txt则命名为计算机名

新建文本文档在文本文档里输入:
dir *.* /a /b /s >1.txt
保存为 提取名字.bat
文件名字被提取到当前文件夹的1.txt里面了!也可以提取某类型的文件比如*.mp3 或者a*.mp3

参 数:
-1 每列仅显示一个文件或目录名称。
-a或--all 下所有文件和目录。
-A或--almost-all 显示所有文件和目录,但不显示现行目录和上层目录。
-b或--escape 显示脱离字符。
-B或--ignore-backups 忽略备份文件和目录。
-c 以更改时间排序,显示文件和目录。
-C 以又上至下,从左到右的直行方式显示文件和目录名称。
-d或--directory 显示目录名称而非其内容。
-D或--dired 用Emacs的模式产生文件和目录列表。
-f 此参数的效果和同时指定"aU"参数相同,并关闭"lst"参数的效果。
-F或--classify 在执行文件,目录,Socket,符号连接,管道名称后面,各自加上"*","/","=","@","|"号。
-g 次参数将忽略不予处理。
-G或--no-group 不显示群组名称。
-h或--human-readable 用"K","M","G"来显示文件和目录的大小。
-H或--si 此参数的效果和指定"-h"参数类似,但计算单位是1000Bytes而非1024Bytes。
-i或--inode 显示文件和目录的inode编号。
-I<范本样式>或--ignore=<范本样式> 不显示符合范本样式的文件或目录名称。
-k或--kilobytes 此参数的效果和指定"block-size=1024"参数相同。
-l 使用详细格式列表。
-L或--dereference 如遇到性质为符号连接的文件或目录,直接列出该连接所指向的原始文件或目录。
-m 用","号区隔每个文件和目录的名称。
-n或--numeric-uid-gid 以用户识别码和群组识别码替代其名称。
-N或--literal 直接列出文件和目录名称,包括控制字符。
-o 此参数的效果和指定"-l" 参数类似,但不列出群组名称或识别码。
-p或--file-type 此参数的效果和指定"-F"参数类似,但不会在执行文件名称后面加上"*"号。
-q或--hide-control-chars 用"?"号取代控制字符,列出文件和目录名称。
-Q或--quote-name 把文件和目录名称以""号标示起来。
-r或--reverse 反向排序。
-R或--recursive 递归处理,将指定目录下的所有文件及子目录一并处理。
-s或--size 显示文件和目录的大小,以区块为单位。
-S 用文件和目录的大小排序。
-t 用文件和目录的更改时间排序。
-T<跳格字符>或--tabsize=<跳格字数> 设置跳格字符所对应的空白字符数。
-u 以最后存取时间排序,显示文件和目录。
-U 列出文件和目录名称时不予排序。
-v 文件和目录的名称列表以版本进行排序。
-w<每列字符数>或--width=<每列字符数> 设置每列的最大字符数。
-x 以从左到右,由上至下的横列方式显示文件和目录名称。
-X 以文件和目录的最后一个扩展名排序。
--block-size=<区块大小> 指定存放文件的区块大小。
--color=<列表格式> 培植文件和目录的列表格式。
--full-time 列出完整的日期与时间。
--help 在线帮助。
--indicator-style=<标注样式> 在文件和目录等名称后面加上标注,易于辨识该名称所属的类型。
--quoting-syte=<引号样式> 把文件和目录名称以指定的引号样式标示起来。
--show-control-chars 在文件和目录列表时,使用控制字符。
--sort=<排序方式> 配置文件和目录列表的排序方式。
--time=<时间戳记> 用指定的时间戳记取代更改时间。
--version 显示版本信息。

批量重命名
新建文本文档在文本文档里输入:
@for /f %%a in (A.txt) do @(
if exist %%a for /f %%b in (B.txt) do (
rename %%a %%b))
保存为 批量改名.bat
A.txt 是原来的文件名
B.txt 是修改后的文件名
一行对应一个名字不能有空格同时注意文件属性
a.txt :
NBA直播录像1.3gp
NBA直播录像2.3gp
NBA直播录像3.3gp
NBA直播录像4.3gp
b.txt :
NBA直播录像第一场.3gp
NBA直播录像第二场.3gp
NBA直播录像第三场.3gp
NBA直播录像第四场.3gp
参考技术A 一个简单的、、、

.版本 2
.支持库 EThread

.程序集 窗口程序集1
.程序集变量 是否停止, 逻辑型
.程序集变量 列表框文件名, 文本型, , "0"

.子程序 __启动窗口_创建完毕

编辑框1.内容 = 取运行目录 () + “\”
组合框1.加入项目 (“*”, )
组合框1.加入项目 (“exe”, )
组合框1.加入项目 (“jpg”, )
组合框1.加入项目 (“bmp”, )
组合框1.现行选中项 = 0

.子程序 _按钮1_被单击

是否停止 = 假
启动线程 (&子程序1, , )

.子程序 子程序1
.局部变量 表项
.局部变量 路径, 文本型
.局部变量 文件名, 文本型

.如果真 (是否停止 = 真) ' 搜索被停止,则返回
返回 ()
.如果真结束
文件名 = 寻找文件 (编辑框1.内容 + 组合框1.内容, )
.判断循环首 (文件名 ≠ “”) ' 显示找到的文件
列表框1.加入项目 (文件名, )
加入成员 (列表框文件名, 编辑框1.内容 + 文件名)
文件名 = 寻找文件 (, )
.判断循环尾 ()

.子程序 _按钮2_被单击

是否停止 = 真
参考技术B 判断循环首(返回文件名!="")
返回文件名=寻找文件(“D:\*.*”,)
列表框。添加项目还是什么(记不太清楚了)=“D:\”+返回文件名
判断循环尾

按照这个伪码自己去试一下吧~应该能做出的!!

以上是关于C语言:如何得到指定地址的文件夹中所有文件的文件名和其修改时间 包括子文件内的的主要内容,如果未能解决你的问题,请参考以下文章

如何在网页中得到本地磁盘上的文件列表

c语言怎样读取指定RAM存储单元的数据出来 比如我要读取0XF0 RAM地址的值应如何实现.

C语言:如何遍历指定的文件夹(可以包括子文件夹)中的每一个文件名

c语言删除文件中的指定的一行数据怎么做

求汇编语言将一个内存块拷贝到指定地址的代码

请我如何c语言遍历文件夹