FILE_NOTIFY_INFORMATION不支持Utf-8文件名

时间:2012-11-07 10:22:32

标签: c++ qt winapi unicode filenames

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

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

1 个答案:

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