Win32遍历指定路径下的文件(Shell实现)
2013-02-26 12:21
399 查看
其实有很多种方法实现遍历指定路径下的文件,最普通的可能就是用FindFirstFile、FindNextFile等API来实现,这种实现方法也可以,但是,如果文件夹时里面有子文件夹的话,用这个方法实现起来就有点麻烦,可能要用递归,而递归这种方式效率是个很大的问题,在这不打算讲这种方法,下面要说的是另一种方式------Windows
Shell。
其实用Shell来实现,思路很简单,先通过某种方式得到对应路径的PIDL,然后再得到与之对应的IShellFolder对象,再用IShellFolder::EnumObjects得到IEnumIDList接口,最终用IEnumIDList接口来遍历所有的文件。思路是这样子的,但这里面还是涉及到了很多关于Shell的概念,在看下面这段代码之前,需要搞明白,不然看起来可能很费劲。
对上面的程序简单说明一下:
// +1 那句,首先得到桌面所对就的IShellFolder对象,可以通过它得到指定路径的PIDL。
// +2 那句,调用ParseDisplayName方法来得到指定路径的PIDL,注意,该方法第三个参数类型是LPWSTR,不是LPCWSTR,这意味着它内部可能会改这个参数。
// +3 那句,通过ShellFolder Bind 一下,得到一个新的ShellFolder,传入一个PIDL,这个PIDL就是第二步得到来的。
// +4 那句,枚举出IEnumIDList接口对象,通过调用它的Next方法,就能取出每一个子元素的PIDL,再通过这个PIDL来得到其对应的路径。
// 最后别忘记释放COM接口,不然就会有内存泄漏。
下面这一段代码就是根据一个PIDL得到其路径,当然,这也可以写成一个函数,调用方便。
Shell。
其实用Shell来实现,思路很简单,先通过某种方式得到对应路径的PIDL,然后再得到与之对应的IShellFolder对象,再用IShellFolder::EnumObjects得到IEnumIDList接口,最终用IEnumIDList接口来遍历所有的文件。思路是这样子的,但这里面还是涉及到了很多关于Shell的概念,在看下面这段代码之前,需要搞明白,不然看起来可能很费劲。
BOOL GetAllFilesFromFolderPath(IN LPCTSTR lpFolderPath, OUT vector<wstring> &vctFiles) { if ( !PathFileExists(lpFolderPath) ) { return FALSE; } WCHAR szFolderPath[MAX_PATH] = { 0 }; IShellFolder *psfDesktop = NULL; IShellFolder *psfWorkDir = NULL; IEnumIDList *penumIDList = NULL; LPITEMIDLIST pidworkDir = NULL; wcscpy_s(szFolderPath, MAX_PATH, lpFolderPath); // +1 HRESULT hr = SHGetDesktopFolder(&psfDesktop); if (SUCCEEDED(hr)) { // +2 hr = psfDesktop->ParseDisplayName(NULL, NULL, szFolderPath, NULL, &pidworkDir, NULL); } if (SUCCEEDED(hr)) { // +3 hr = psfDesktop->BindToObject(pidworkDir, NULL, IID_PPV_ARGS(&psfWorkDir)); } if (SUCCEEDED(hr)) { // +4 hr = psfWorkDir->EnumObjects(NULL, SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penumIDList); } if (SUCCEEDED(hr)) { ULONG celtFetched = 0; LPITEMIDLIST pidChild = NULL; while (SUCCEEDED(penumIDList->Next(1, &pidChild, &celtFetched)) && (1 == celtFetched)) { // Get the file path from the PIDL of the item. LPITEMIDLIST pRealIDL = NULL; HRESULT hr = SHGetRealIDL(psfWorkDir, pidChild, &pRealIDL); if (SUCCEEDED(hr)) { STRRET strName; hr = psfWorkDir->GetDisplayNameOf(pRealIDL, SHGDN_FORPARSING, &strName); if (SUCCEEDED(hr)) { WCHAR szName[MAX_PATH] = { 0 }; hr = StrRetToBuf(&strName, pRealIDL, szName, MAX_PATH); if (SUCCEEDED(hr)) { vctFiles.push_back(szName); } } CoTaskMemFree(pRealIDL); } CoTaskMemFree(pidChild); } } // -4 SAFE_RELEASE(penumIDList); // -3 SAFE_RELEASE(psfWorkDir); // -2 CoTaskMemFree(pidworkDir); // -1 SAFE_RELEASE(psfDesktop); return (vctFiles.size() > 0); }
对上面的程序简单说明一下:
// +1 那句,首先得到桌面所对就的IShellFolder对象,可以通过它得到指定路径的PIDL。
// +2 那句,调用ParseDisplayName方法来得到指定路径的PIDL,注意,该方法第三个参数类型是LPWSTR,不是LPCWSTR,这意味着它内部可能会改这个参数。
// +3 那句,通过ShellFolder Bind 一下,得到一个新的ShellFolder,传入一个PIDL,这个PIDL就是第二步得到来的。
// +4 那句,枚举出IEnumIDList接口对象,通过调用它的Next方法,就能取出每一个子元素的PIDL,再通过这个PIDL来得到其对应的路径。
// 最后别忘记释放COM接口,不然就会有内存泄漏。
下面这一段代码就是根据一个PIDL得到其路径,当然,这也可以写成一个函数,调用方便。
LPITEMIDLIST pRealIDL = NULL; HRESULT hr = SHGetRealIDL(psfWorkDir, pidChild, &pRealIDL); if (SUCCEEDED(hr)) { STRRET strName; hr = psfWorkDir->GetDisplayNameOf(pRealIDL, SHGDN_FORPARSING, &strName); if (SUCCEEDED(hr)) { WCHAR szName[MAX_PATH] = { 0 }; hr = StrRetToBuf(&strName, pRealIDL, szName, MAX_PATH); if (SUCCEEDED(hr)) { vctFiles.push_back(szName); } } CoTaskMemFree(pRealIDL); }
相关文章推荐
- c#如何实现对指定路径文件夹的遍历并复制里面所有文件到指定路径
- python和shell脚本实现查看大文件指定区域范围内的文件内容
- php实现遍历目录并删除指定文件中指定内容
- Java实现获取指定路径下的指定格式的文件,如bcp,txt等
- Ruby和SHELL中如何遍历指定目录的文件 推荐
- Linux下 C语言实现遍历指定目录下指定格式的文件
- php实现文件上传到指定文件夹,文件路径或名字存入数据库,如何实现啊
- 3、用shell遍历文件的每一行,和获取指定行的信息。
- PHP递归遍历指定文件夹内的文件实现方法
- as通过gradle实现多渠道打包+使用配置文件进行版本管理+指定apk输出路径和apk文件名
- [安卓源代码]简单实现SD卡上遍历所有文件夹寻找指定格式文件
- java 读取目录及子目录下指定文件名的路径 并放到一个List数组里面返回遍历和写到文件里
- C#备份及还原数据库的实现代码(粗略) // 利用C#还原数据库(SQL SERVER)备份文件到指定路径
- Shell根据给定路径读取其中的文件并输出到指定的路径
- Python3实现从指定路径查找文件的方法
- opencv 遍历指定路径下所有文件的内容
- shell 脚本实现的遍历目录修改子目录及其文件权限
- 分别用Shell和Python遍历查询Hdfs文件路径
- php glob实现目录文件遍历与寻找与模式匹配的文件路径
- 使用Spring Log4jConfigListener实现Log4j中以相对路径指定的日志文件