我正在尝试查看文件夹更改并通知添加的文件名,因此这是我的代码
bool FileWatcher::NotifyChange()
{
// Read the asynchronous result of the previous call to ReadDirectory
DWORD dwNumberbytes;
GetOverlappedResult(hDir, &overl, &dwNumberbytes, FALSE);
// Browse the list of FILE_NOTIFY_INFORMATION entries
FILE_NOTIFY_INFORMATION *pFileNotify = (FILE_NOTIFY_INFORMATION *)buffer[curBuffer];
// Switch the 2 buffers
curBuffer = (curBuffer + 1) % (sizeof(buffer)/(sizeof(buffer[0])));
SecureZeroMemory(buffer[curBuffer], sizeof(buffer[curBuffer]));
// start a new asynchronous call to ReadDirectory in the alternate buffer
ReadDirectoryChangesW(
hDir, /* handle to directory */
&buffer[curBuffer], /* read results buffer */
sizeof(buffer[curBuffer]), /* length of buffer */
FALSE, /* monitoring option */
FILE_NOTIFY_CHANGE_FILE_NAME ,
//FILE_NOTIFY_CHANGE_LAST_WRITE, /* filter conditions */
NULL, /* bytes returned */
&overl, /* overlapped buffer */
NULL); /* completion routine */
for (;;) {
(pFileNotify->Action == FILE_ACTION_ADDED)
{
qDebug()<<"in NotifyChange if ";
char szAction[42];
char szFilename[MAX_PATH] ;
memset(szFilename,'\0',sizeof( szFilename));
strcpy(szAction,"added");
wcstombs( szFilename, pFileNotify->FileName, MAX_PATH);
qDebug()<<"pFileNotify->FileName : "<<QString::fromWCharArray(pFileNotify->FileName)<<"\nszFilename : "<<QString(szFilename);
}
// step to the next entry if there is one
if (!pFileNotify->NextEntryOffset)
return false;
pFileNotify = (FILE_NOTIFY_INFORMATION *)((PBYTE)pFileNotify + pFileNotify->NextEntryOffset);
}
pFileNotify=NULL;
return true;
}
除非添加了带有阿拉伯名字的文件,否则它会正常工作
pFileNotify->FileName : "??? ???????.txt"
szFilename : ""
我如何支持UTF-8代码文件名??? 任何想法,请。
答案 0 :(得分:3)
除了FILE_NOTIFY_INFORMATION::FileName
不被空终止之外,它没有任何问题。
<强>文件名:强> 一个可变长度字段,包含相对于目录句柄的文件名。文件名采用Unicode字符格式,非空终止。 如果文件有短名称和长名称,则该函数将返回其中一个名称,但未指定哪个名称。
FileNameLength:记录的文件名部分的大小(以字节为单位)。请注意,此值不包括终止空字符。
您必须使用FILE_NOTIFY_INFORMATION::FileNameLength / sizeof(WCHAR)
来获取FileName指向的wchars中字符串的长度。所以在你的情况下,正确的方法是:
size_t cchFileNameLength = pFileNotify->FileNameLength / sizeof(WCHAR);
QString::fromWCharArray( pFileNotify->FileName, cchFileNameLength );
如果你需要使用一个期望字符串为空终止的函数(比如wcstombs),你必须分配一个大小为FILE_NOTIFY_INFORMATION::FileNameLength + sizeof(WCHAR)
的临时缓冲区,并自行将其终止。
对于空的szFilename和问号,这只是将包含不可转换字符的UTF16(NTFS)文件名转换为ANSI的结果。如果没有可能的转换,wcstombs将返回错误,QDebug会将任何不可转换的字符转换为?
。
如果wcstombs遇到宽字符,则无法转换为多字节字符,它会返回-1强制转换为类型size_t并将errno设置为EILSEQ。
因此,如果您需要支持unicode文件名,请不要将它们转换为ANSI,并使用支持unicode的函数专门处理它们。