在某些情况下,会有使用长路径(大于MAX_PATH/260字符)的需求,如网络文件管理之类的,WindowsNT之后的NTFS文件系统其实是支持这样的操作的,但需求毕竟比较特殊,而且Explorer资源浏览器都不支持它,所以很少被认识到.
这里我写了一个子目递归调用函数,原型:
INT32 LongPathFileFind(LPWSTR lpPath, //被搜索路径
IfFindAFile fIfFind, //搜到子文件时的回调
INT32 nFindMode) //是否递归方式
IfFindAFile 定义:
typedef INT32 (CALLBACKFUNC *IfFindAFile)(LPWSTR lpFileName, //找出的文件名
INT32 nFindCount); //文件的序号
使用它们就可以在32767字符长度的目录之中自由穿梭了。
测试代码在VC7下运行成功,AddASubDir测试回调功能是加入子目录,注意这样会无限的生成子目录,不需要这样的话,请停止运行。
实例代码如下:
//TtestLongPathFind.cpp
#include "stdafx.h"
#define LONG_FIND_SUCCSS 0
#define LONG_FIND_ERROR_FIRST -2
#define CALLBACKFUNC __stdcall
#define FIND_MODE_RECURSIVE 0x01
typedef INT32 (CALLBACKFUNC *IfFindAFile)(LPWSTR lpFileName, INT32 nFindCount);
INT32 CALLBACKFUNC AddASubDir(LPWSTR lpFileName, INT32 nFindCount)
{
WCHAR *pszCreatePathName = new WCHAR[1024 * 1024];
wsprintfW(pszCreatePathName, L"%s//asdfasdfasdf", lpFileName);
if(CreateDirectoryW(pszCreatePathName, NULL) == FALSE)
{
delete[] pszCreatePathName;
return -1;
}
delete[] pszCreatePathName;
return 0;
}
INT32 LongPathFileFind(LPWSTR lpPath, IfFindAFile fIfFind, INT32 nFindMode)
{
WIN32_FIND_DATAW WFD;
HANDLE hFileFind;
INT32 nRet = LONG_FIND_SUCCSS;
WCHAR *pszFindFile = new WCHAR[1024 * 1024];
WCHAR *pszFileFullPath = new WCHAR[1024 * 1024];
while(TRUE)
{
wsprintfW(pszFindFile, L"%s//*", lpPath);
hFileFind = ::FindFirstFileW(pszFindFile, &WFD);
INT32 nFileCount = 0;
if( hFileFind == INVALID_HANDLE_VALUE )
{
nRet = LONG_FIND_ERROR_FIRST;
break;
}
do
{
if(::FindNextFileW(hFileFind, &WFD) == FALSE)
break;
if(WFD.cFileName[0] != L"."[0])
{
wsprintfW(pszFileFullPath, L"%s//%s", lpPath, WFD.cFileName);
fIfFind(pszFileFullPath, nFileCount);
if(nFindMode == FIND_MODE_RECURSIVE)
{
if(WFD.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
LongPathFileFind(pszFileFullPath, fIfFind, nFindMode);
}
}
}
nFileCount++;
}while(TRUE);
::FindClose(hFileFind);
}
delete[] pszFindFile;
return nRet;
}
int _tmain(int argc, _TCHAR* argv[])
{
WCHAR *pszPathName = new WCHAR[1024 * 1024];
wsprintfW(pszPathName, L"%s", L"?//C://Test");
INT32 nCount = 0;
LongPathFileFind( pszPathName , AddASubDir, FIND_MODE_RECURSIVE);
delete[] pszPathName;
return 0;
}