您的位置:首页 > 编程语言 > C语言/C++

C++获取文件夹和文件信息

2013-07-16 15:14 447 查看


[title3]C++获取文件夹和文件信息—_findfirst,_findnext和_findclose方法[/title3]

BinhuaLiu


介绍

本文的目的是介绍C++中如何通过_findfirst,和_findclose方法来查找文件夹中所有子文件夹和文件.本文还讨论了使用SHGetFileInfo函数和结构体来获取文件/文件夹的详细信息。


库和头文件

为了使用_findfirst,_findnext和_findclose方法,需要包含头文件:

#include<io.h>
io.h中包含大量对文件系统进行底层操作的函数。
本文例子中使用了字符串宏,因此还需要包含头文件:

#include<AtlBase.h>


函数族和宏定义

为了适应各种不同的编译环境,Microsoft往往对C++函数给出多个版本的实现。_findfirst,_findnext和以及_finddata_t根据以下编译环境的不同给出了多种实现

采用多字符集或Unicode字符集
采用32位时间或64位时间
采用32位文件长度或64位文件长度

所有函数实现列表如下:
MBCS/

Unicode
timetypefilelengthtypeFunctions
MBCS32bit32bit_findfirst32,_findnext32,_finddata32_t
MBCS32bit64bit_findfirst32i64,_findnext32i64,_finddata32i64_t
MBCS64bit32bit_findfirst64i32,_findnext64i32,_finddata64i32_t
MBCS64bit64bit_findfirst64,_findnext64,__finddata64_t
Unicode32bit32bit_wfindfirst32,_wfindnext32,_wfinddata32_t
Unicode32bit64bit_wfindfirst32i64,_wfindnext32i64,_wfinddata32i64_t
Unicode64bit32bit_wfindfirst64i32,_wfindnext64i32,_wfinddata64i32_t
Unicode64bit64bit_wfindfirst64,_wfindnext64,_wfinddata64_t
_findclose方法只有一种实现。

C++同时提供了大量的宏,来保证我们的代码即使不经过修改,也可以适应不同的编译环境,这些宏全部或部分根据下面2个编译环境来决定最终被替换成哪个函数:

在_UNICODE被定义时,使用支持UNICODE的实现,在_MBCS被定义或2者都没有被定义时,使用支持MBCS的实现。
在_USE_32BIT_TIME_T被定义时使用支持32bit时间类型的函数,在其没有被定义时采用64bit时间类型的函数。

下面列出_findfirst几种常用的宏:

不同编译环境时对应的函数
_findfirst_findfirst32
_tfindfirst_MBCS定义,_USE_32BIT_TIME_T定义时:_findfirst32

_MBCS定义,_USE_32BIT_TIME_TNOT定义时:_findfirst64i32

_UNICODE定义,_USE_32BIT_TIME_T定义时:_wfindfirst32

_UNICODE定义,_USE_32BIT_TIME_TNOT定义时:_wfindfirst64i32
_tfindfirst32_MBCS定义时:_findfirst32

_UNICODE定义时:_wfindfirst32
_tfindfirst64_MBCS定义时:_findfirst64

_UNICODE定义时:_wfindfirst64
为了让我们的代码有很好的兼容性,下面我们都采用_tfindfirst64宏来讲解,_findfirst的其他宏和函数在用法上与其是一致的。其他用到的函数也都是宏,保证代码在多字符集和Unicode字符集下都不需修改即能通过编译。



函数用法


intptr_t
_tfindfirst64(
LPCTSTR
filespec,
struct
_tfinddata64_t*fileinfo)
int
_tfindnext64(
intptr_t
handle,
struct
_tfinddata64_t*fileinfo);
int
_findclose(
intptr_t
handle);

上面的函数定义中,_tfindfirst64,_tfinddata64_t,_tfindnext64,LPCTSTR都是宏,LPCTSTR是字符串宏,在多字符集时等于constchar*,Unicode字符集是等于constwchar*。


_tfindfirst64函数:该函数用于得到指定路径filespec下的第一个文件(或者文件夹),filespec支持通配符,例如"c:/*.*”指查找C盘所有的文件和子目录。fileinfo由函数填充后返回,记录第一个文件(或文件夹)的信息,返回值是一个唯一性搜索句柄,用来传递给_tfindnext64查找下一个文件,或者传递给_findclose来关闭该句柄。如果调用失败,返回值等于-1.
_tfindnext64函数:该函数用于搜索下一个文件(或文件夹),参数handle是之前调用_tfindfirst64返回的句柄,fileinfo由函数填充后返回,记录当前文件(或文件夹)的信息,如果查找成功,返回值为0,否则为-1.我们一般都采用do…while循环不断调用_tfindnext64函数来遍历当前目录下所有的子目录和文件,直到返回-1时结束。
_findclose函数:用于结束查找时关闭句柄,参数handle是之前调用_tfindfirst64返回的句柄。
_tfinddata64_t结构体:我们以_wfinddata64_t为例,其有如下定义

struct
_wfinddata64_t{
unsignedattrib;
__time64_t
time_create;
/*-1forFATfilesystems*/
__time64_t
time_access;
/*-1forFATfilesystems*/
__time64_t
time_write;
__int64
size;
wchar_t
name[260];
};
time_create,time_access,time_write分别指创建时间,最近访问时间,和最后修改时间;name为文件(或文件夹)名称;attrib描述的文件的系统属性,它由多个attributes组合而成,在MSDN中描述如下:
_A_ARCHArchive.Setwheneverthefileischanged,andclearedbytheBACKUPcommand.Value:0x20
_A_HIDDENHiddenfile.NotnormallyseenwiththeDIRcommand,unlessthe/AHoptionisused.Returnsinformationaboutnormalfilesaswellasfileswiththisattribute.Value:0x02
_A_NORMALNormal.Filecanbereadorwrittentowithoutrestriction.Value:0x00
_A_RDONLYRead-only.Filecannotbeopenedforwriting,andafilewiththesamenamecannotbecreated.Value:0x01
_A_SUBDIRSubdirectory.Value:0x10
_A_SYSTEMSystemfile.NotnormallyseenwiththeDIRcommand,unlessthe/ASoptionisused.Value:0x04
_A_SUBDIR属性表示该对象是一个子目录,我们可以探测这个位是否被设置来判断这是一个文件还是文件夹。这样,我们就可以采用递归的办法,来获取每个子目录下的文件信息。

下面的是一段演示代码,采用递归的方法,获取当前目录和所有子目录下文件的信息,并把它们的文件属性打印出来,并把每个文件的全路径存储在一个vector结构中。

#include<io.h>
#include<vector>
#include<AtlBase.h>
#include<time.h>
using
namespace
std;
void
GetAllFileInfo(
LPCTSTR
path,vector<
LPCTSTR
>&filesPathVector)
{
//findthefirstfile
_tfinddata64_tc_file;
intptr_t
hFile;
TCHAR
root[MAX_PATH];
_tcscpy(root,path);
_tcscat(root,_T(
"//*.*"
));
hFile=_tfindfirst64(root,&c_file);
if
(hFile==-1)
return
;
//searchallfilesrecursively.
do
{
if
(_tcslen(c_file.name)==1&&c_file.name[0]==_T(
'.'
)
||_tcslen(c_file.name)==2&&c_file.name[0]==_T(
'.'
)&&c_file.name[1]==_T(
'.'
))
continue
;
TCHAR
*fullPath=
new
TCHAR
[MAX_PATH];
_tcscpy(fullPath,path);
_tcscat(fullPath,_T(
"//"
));
_tcscat(fullPath,c_file.name);
if
(c_file.attrib&_A_SUBDIR)
{
GetAllFileInfo(fullPath,filesPathVector);
}
else
{
//storefullfilepathinvector.
filesPathVector.push_back(fullPath);
//printfileinfo
_tprintf(_T(
"FileName:%s/r/n"
),fullPath);
_tprintf(_T(
"ReadOnly:%s/r/n"
),
(c_file.attrib&_A_RDONLY)?_T(
"Y"
):_T(
"N"
));
_tprintf(_T(
"Hidden:%s/r/n"
),
(c_file.attrib&_A_HIDDEN)?_T(
"Y"
):_T(
"N"
));
_tprintf(_T(
"System:%s/r/n"
),
(c_file.attrib&_A_SYSTEM)?_T(
"Y"
):_T(
"N"
));
_tprintf(_T(
"Arch:%s/r/n"
),
(c_file.attrib&_A_ARCH)?_T(
"Y"
):_T(
"N"
));
TCHAR
timeBuffer[30];
_tctime64_s(timeBuffer,_countof(timeBuffer),&c_file.time_write);
_tprintf(_T(
"WriteTime:%.24s/r/n/r/n"
),timeBuffer);
}
}
while
(_tfindnext64(hFile,&c_file)==0);
//closesearchhandle
_findclose(hFile);
}
int
_tmain(
int
argc,_TCHAR*argv[])
{
vector<
LPCTSTR
>filesPathVector;
GetAllFileInfo(_T(
"d://FolderForTest"
),filesPathVector);
return
0;
}
打印的结果:
FileName:d:/FolderForTest/a.txt

ReadOnly:N

Hidden:N

System:N

Arch:Y

WriteTime:SunJun0612:21:222010
FileName:d:/FolderForTest/sub1/b

ReadOnly:N

Hidden:N

System:N

Arch:Y

WriteTime:MonJun0716:33:452010



SHGetFileInfo方法

_tfinddata64_t结构体存储的信息很少,我们可能希望得到更多的文件信息,比如文件的类型,文件的图标等等,这就需要用到SHGetFileInfo函数:

DWORD_PTR
SHGetFileInfo(
__in
LPCTSTR
pszPath,
__in
DWORD
dwFileAttributes,
__outSHFILEINFO*psfi,
__in
UINT
cbFileInfo,
__in
UINT
uFlags
);
这是一个WindowsShell函数,需要的头文件及库为:
HeaderShellapi.h
LibraryShell32.lib
DLLShell32.dll
pszPath指定文件的路径,uFlags指定希望获取的文件信息,而获取的文件的信息通过结构体SHFILEINFO*psfi返回。我们把这段代码加在之前的代码中,示例如下:

void
GetRichFileInfo(
LPCTSTR
path)
{
SHFILEINFOshfi;
//getfilename,typenameandattributes.ifneedmore,shouldconbinedmoreflagby'|'
SHGetFileInfo(path,0,&shfi,
sizeof
(shfi),SHGFI_TYPENAME|SHGFI_DISPLAYNAME|SHGFI_ATTRIBUTES);
_tprintf(_T(
"DisplayName:%s/r/n"
),shfi.szDisplayName);
_tprintf(_T(
"TypeName:%s/r/n/r/n"
),shfi.szTypeName);
}
int
_tmain(
int
argc,_TCHAR*argv[])
{
vector<
LPCTSTR
>filesPathVector;
GetAllFileInfo(_T(
"d://FolderForTest"
),filesPathVector);
for
(
int
i=0;i<filesPathVector.size();i++)
{
LPCTSTR
path=filesPathVector.at(i);
GetRichFileInfo(path);
}
return
0;
}
运行结果
DisplayName:a.txt

TypeName:TextDocument
DisplayName:b

TypeName:File
[title3]C++获取文件夹和文件信息—_findfirst,_findnext和_findclose方法[/title3]

BinhuaLiu


介绍

本文的目的是介绍C++中如何通过_findfirst,和_findclose方法来查找文件夹中所有子文件夹和文件.本文还讨论了使用SHGetFileInfo函数和结构体来获取文件/文件夹的详细信息。


库和头文件

为了使用_findfirst,_findnext和_findclose方法,需要包含头文件:

#include<io.h>
io.h中包含大量对文件系统进行底层操作的函数。
本文例子中使用了字符串宏,因此还需要包含头文件:

#include<AtlBase.h>


函数族和宏定义

为了适应各种不同的编译环境,Microsoft往往对C++函数给出多个版本的实现。_findfirst,_findnext和以及_finddata_t根据以下编译环境的不同给出了多种实现

采用多字符集或Unicode字符集
采用32位时间或64位时间
采用32位文件长度或64位文件长度

所有函数实现列表如下:
MBCS/

Unicode
timetypefilelengthtypeFunctions
MBCS32bit32bit_findfirst32,_findnext32,_finddata32_t
MBCS32bit64bit_findfirst32i64,_findnext32i64,_finddata32i64_t
MBCS64bit32bit_findfirst64i32,_findnext64i32,_finddata64i32_t
MBCS64bit64bit_findfirst64,_findnext64,__finddata64_t
Unicode32bit32bit_wfindfirst32,_wfindnext32,_wfinddata32_t
Unicode32bit64bit_wfindfirst32i64,_wfindnext32i64,_wfinddata32i64_t
Unicode64bit32bit_wfindfirst64i32,_wfindnext64i32,_wfinddata64i32_t
Unicode64bit64bit_wfindfirst64,_wfindnext64,_wfinddata64_t
_findclose方法只有一种实现。

C++同时提供了大量的宏,来保证我们的代码即使不经过修改,也可以适应不同的编译环境,这些宏全部或部分根据下面2个编译环境来决定最终被替换成哪个函数:

在_UNICODE被定义时,使用支持UNICODE的实现,在_MBCS被定义或2者都没有被定义时,使用支持MBCS的实现。
在_USE_32BIT_TIME_T被定义时使用支持32bit时间类型的函数,在其没有被定义时采用64bit时间类型的函数。

下面列出_findfirst几种常用的宏:

不同编译环境时对应的函数
_findfirst_findfirst32
_tfindfirst_MBCS定义,_USE_32BIT_TIME_T定义时:_findfirst32

_MBCS定义,_USE_32BIT_TIME_TNOT定义时:_findfirst64i32

_UNICODE定义,_USE_32BIT_TIME_T定义时:_wfindfirst32

_UNICODE定义,_USE_32BIT_TIME_TNOT定义时:_wfindfirst64i32
_tfindfirst32_MBCS定义时:_findfirst32

_UNICODE定义时:_wfindfirst32
_tfindfirst64_MBCS定义时:_findfirst64

_UNICODE定义时:_wfindfirst64
为了让我们的代码有很好的兼容性,下面我们都采用_tfindfirst64宏来讲解,_findfirst的其他宏和函数在用法上与其是一致的。其他用到的函数也都是宏,保证代码在多字符集和Unicode字符集下都不需修改即能通过编译。



函数用法


intptr_t
_tfindfirst64(
LPCTSTR
filespec,
struct
_tfinddata64_t*fileinfo)
int
_tfindnext64(
intptr_t
handle,
struct
_tfinddata64_t*fileinfo);
int
_findclose(
intptr_t
handle);

上面的函数定义中,_tfindfirst64,_tfinddata64_t,_tfindnext64,LPCTSTR都是宏,LPCTSTR是字符串宏,在多字符集时等于constchar*,Unicode字符集是等于constwchar*。


_tfindfirst64函数:该函数用于得到指定路径filespec下的第一个文件(或者文件夹),filespec支持通配符,例如"c:/*.*”指查找C盘所有的文件和子目录。fileinfo由函数填充后返回,记录第一个文件(或文件夹)的信息,返回值是一个唯一性搜索句柄,用来传递给_tfindnext64查找下一个文件,或者传递给_findclose来关闭该句柄。如果调用失败,返回值等于-1.
_tfindnext64函数:该函数用于搜索下一个文件(或文件夹),参数handle是之前调用_tfindfirst64返回的句柄,fileinfo由函数填充后返回,记录当前文件(或文件夹)的信息,如果查找成功,返回值为0,否则为-1.我们一般都采用do…while循环不断调用_tfindnext64函数来遍历当前目录下所有的子目录和文件,直到返回-1时结束。
_findclose函数:用于结束查找时关闭句柄,参数handle是之前调用_tfindfirst64返回的句柄。
_tfinddata64_t结构体:我们以_wfinddata64_t为例,其有如下定义

struct
_wfinddata64_t{
unsignedattrib;
__time64_t
time_create;
/*-1forFATfilesystems*/
__time64_t
time_access;
/*-1forFATfilesystems*/
__time64_t
time_write;
__int64
size;
wchar_t
name[260];
};
time_create,time_access,time_write分别指创建时间,最近访问时间,和最后修改时间;name为文件(或文件夹)名称;attrib描述的文件的系统属性,它由多个attributes组合而成,在MSDN中描述如下:
_A_ARCHArchive.Setwheneverthefileischanged,andclearedbytheBACKUPcommand.Value:0x20
_A_HIDDENHiddenfile.NotnormallyseenwiththeDIRcommand,unlessthe/AHoptionisused.Returnsinformationaboutnormalfilesaswellasfileswiththisattribute.Value:0x02
_A_NORMALNormal.Filecanbereadorwrittentowithoutrestriction.Value:0x00
_A_RDONLYRead-only.Filecannotbeopenedforwriting,andafilewiththesamenamecannotbecreated.Value:0x01
_A_SUBDIRSubdirectory.Value:0x10
_A_SYSTEMSystemfile.NotnormallyseenwiththeDIRcommand,unlessthe/ASoptionisused.Value:0x04
_A_SUBDIR属性表示该对象是一个子目录,我们可以探测这个位是否被设置来判断这是一个文件还是文件夹。这样,我们就可以采用递归的办法,来获取每个子目录下的文件信息。

下面的是一段演示代码,采用递归的方法,获取当前目录和所有子目录下文件的信息,并把它们的文件属性打印出来,并把每个文件的全路径存储在一个vector结构中。

#include<io.h>
#include<vector>
#include<AtlBase.h>
#include<time.h>
using
namespace
std;
void
GetAllFileInfo(
LPCTSTR
path,vector<
LPCTSTR
>&filesPathVector)
{
//findthefirstfile
_tfinddata64_tc_file;
intptr_t
hFile;
TCHAR
root[MAX_PATH];
_tcscpy(root,path);
_tcscat(root,_T(
"//*.*"
));
hFile=_tfindfirst64(root,&c_file);
if
(hFile==-1)
return
;
//searchallfilesrecursively.
do
{
if
(_tcslen(c_file.name)==1&&c_file.name[0]==_T(
'.'
)
||_tcslen(c_file.name)==2&&c_file.name[0]==_T(
'.'
)&&c_file.name[1]==_T(
'.'
))
continue
;
TCHAR
*fullPath=
new
TCHAR
[MAX_PATH];
_tcscpy(fullPath,path);
_tcscat(fullPath,_T(
"//"
));
_tcscat(fullPath,c_file.name);
if
(c_file.attrib&_A_SUBDIR)
{
GetAllFileInfo(fullPath,filesPathVector);
}
else
{
//storefullfilepathinvector.
filesPathVector.push_back(fullPath);
//printfileinfo
_tprintf(_T(
"FileName:%s/r/n"
),fullPath);
_tprintf(_T(
"ReadOnly:%s/r/n"
),
(c_file.attrib&_A_RDONLY)?_T(
"Y"
):_T(
"N"
));
_tprintf(_T(
"Hidden:%s/r/n"
),
(c_file.attrib&_A_HIDDEN)?_T(
"Y"
):_T(
"N"
));
_tprintf(_T(
"System:%s/r/n"
),
(c_file.attrib&_A_SYSTEM)?_T(
"Y"
):_T(
"N"
));
_tprintf(_T(
"Arch:%s/r/n"
),
(c_file.attrib&_A_ARCH)?_T(
"Y"
):_T(
"N"
));
TCHAR
timeBuffer[30];
_tctime64_s(timeBuffer,_countof(timeBuffer),&c_file.time_write);
_tprintf(_T(
"WriteTime:%.24s/r/n/r/n"
),timeBuffer);
}
}
while
(_tfindnext64(hFile,&c_file)==0);
//closesearchhandle
_findclose(hFile);
}
int
_tmain(
int
argc,_TCHAR*argv[])
{
vector<
LPCTSTR
>filesPathVector;
GetAllFileInfo(_T(
"d://FolderForTest"
),filesPathVector);
return
0;
}
打印的结果:
FileName:d:/FolderForTest/a.txt

ReadOnly:N

Hidden:N

System:N

Arch:Y

WriteTime:SunJun0612:21:222010
FileName:d:/FolderForTest/sub1/b

ReadOnly:N

Hidden:N

System:N

Arch:Y

WriteTime:MonJun0716:33:452010



SHGetFileInfo方法

_tfinddata64_t结构体存储的信息很少,我们可能希望得到更多的文件信息,比如文件的类型,文件的图标等等,这就需要用到SHGetFileInfo函数:

DWORD_PTR
SHGetFileInfo(
__in
LPCTSTR
pszPath,
__in
DWORD
dwFileAttributes,
__outSHFILEINFO*psfi,
__in
UINT
cbFileInfo,
__in
UINT
uFlags
);
这是一个WindowsShell函数,需要的头文件及库为:
HeaderShellapi.h
LibraryShell32.lib
DLLShell32.dll
pszPath指定文件的路径,uFlags指定希望获取的文件信息,而获取的文件的信息通过结构体SHFILEINFO*psfi返回。我们把这段代码加在之前的代码中,示例如下:

void
GetRichFileInfo(
LPCTSTR
path)
{
SHFILEINFOshfi;
//getfilename,typenameandattributes.ifneedmore,shouldconbinedmoreflagby'|'
SHGetFileInfo(path,0,&shfi,
sizeof
(shfi),SHGFI_TYPENAME|SHGFI_DISPLAYNAME|SHGFI_ATTRIBUTES);
_tprintf(_T(
"DisplayName:%s/r/n"
),shfi.szDisplayName);
_tprintf(_T(
"TypeName:%s/r/n/r/n"
),shfi.szTypeName);
}
int
_tmain(
int
argc,_TCHAR*argv[])
{
vector<
LPCTSTR
>filesPathVector;
GetAllFileInfo(_T(
"d://FolderForTest"
),filesPathVector);
for
(
int
i=0;i<filesPathVector.size();i++)
{
LPCTSTR
path=filesPathVector.at(i);
GetRichFileInfo(path);
}
return
0;
}
运行结果
DisplayName:a.txt

TypeName:TextDocument
DisplayName:b

TypeName:File

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: