【发布时间】:2018-06-13 04:55:21
【问题描述】:
我有以下代码可以在我的产品中查找文件:
destFolder = "c:\\myproduct\\base\\";
//download and unzip whoisactive.zip from some websites to the installation folder of my product
DownloadAndUnzipSql( "http://www.whoisactive.com/whoisactive.zip", destFolder)
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile(destFolder.c_str(), &ffd);
do {
if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
if ((string(ffd.cFileName).find("whoisactive") != string::npos) && (string(ffd.cFileName).find("sql") != string::npos)){
MoveFile(ffd.cFileName, sqlFile.c_str());
log.Debug(__FUNCTION__, "Succeed to rename file.");
break;
}
}
} while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
以前很好用,最近一个月下载的whoisactive.sql突然找不到了。我检查了 c:\myproduct\base\,whoisactive.sql 在那里,但是当我转储 FindFirstFile 和 FindNextFile 返回的所有文件时,whoisactive.sql 不包括在内。
我认为不是杀毒软件引起的,因为产品环境中没有安装杀毒软件。而且我认为这不是权限问题,因为 whoisactive.sql 已正确下载并解压缩。
我搜索了我的问题,发现以下两篇文章: https://social.msdn.microsoft.com/Forums/vstudio/en-US/4659a528-dd51-4749-b751-a491bbdf5fa0/findfirstfile-caching?forum=vcgeneral Does FindFirstFile/FindNextFile API pair cache results returned?
FindFirstFile 似乎会缓存一个目录的文件列表,所以有时我们可能找不到新添加的文件。但我也不认为这是根本原因,因为奇怪的是我的代码在去年运行良好并且从未失败,并且最近一个月突然找不到 whoisactive.sql 并且直到现在才运行。如果缓存问题是根本原因,那为什么我现在总是可以重现问题?而且很奇怪,代码在我的开发环境下还能运行,但是在产品环境下就不行了。
所以我将我的代码更改为以下代码,然后它可以在产品和开发环境中运行:
destFolder = "c:\\myproduct\\base\\";
//download whoisactive.zip from some websites to the installation folder of my product
Download( "http://www.whoisactive.com/whoisactive.zip", destFolder);
//Unzip the whoisactive.zip and get the extracted file list.
string fileList;
Unzip(destFolder+"\\whoisactive.zip", fileList);
for (int i=0; i<fileList.size(); ++i) {
if (fileList[i].find("sql") != string::npos && fileList[i].find("whoisactive") != string::npos) {
string srcFile = destFolder+"\\"+fileList[i];
string dstFile = destFolder+"\\"+sqlFile;
if (DeleteFile(dstFile.c_str()) == 0)
log.Debug(__FUNCTION__, "Failed to delete file %s, error code is %d.", dstFile.c_str(), GetLastError());
if (MoveFile(srcFile.c_str(), dstFile.c_str()) == 0)
log.Debug(__FUNCTION__, "Failed to rename file %s, error code is %d.", srcFile.c_str(), GetLastError());
break;
}
}
您可以看到变化是我不再在我的代码中使用 FindFirstFile 和 FindNextFile,我只是从 zip 文件中提取文件名并直接访问该文件。那你能告诉我为什么 FindFirstFile 和 FindNextFile 在我之前的代码中找不到下载的 sql 文件吗?谢谢。
【问题讨论】:
-
您没有检查
FindFirstFile的结果,没有使用这些函数的Unicode版本,并且在枚举文件时修改了目标文件夹。 -
在我的情况下 FindFirstFile 返回了一个有效的句柄,但 FindNextFile 仍然没有返回所有文件;所有文件都不使用unicode文件名,如果这个问题是关于unicode版本api的,那么为什么我可以在同一目录中获取其他文件?而且我在枚举的时候没有修改目标文件夹,我在枚举之前修改了文件夹。
-
您正在通过调用
MoveFile修改文件夹。请注意,您只传递了文件名,因此这意味着destFolder被设置为当前工作目录。