0

我正在尝试查看文件夹更改并通知添加的文件名,所以这是我的代码

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 编码文件名???请有任何想法。

4

1 回答 1

3

除了FILE_NOTIFY_INFORMATION::FileName没有被空终止之外,它没有任何问题。

FileName: 一个可变长度字段,包含相对于目录句柄的文件名。文件名采用 Unicode 字符格式,并且不是以 null 结尾的。如果文件同时存在短名称和长名称,则该函数将返回这些名称之一,但未指定哪个名称。

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 的函数专门处理它们。

于 2012-11-07T12:30:54.677 回答