2012-11-07 76 views
0

我試圖觀看更改文件夾,所以在這裏通知添加文件名是我的代碼FILE_NOTIFY_INFORMATION不支持UTF-8的文件名

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代碼文件名??? 請任何想法。

+2

您是否知道pFileNotify-> FileName不是空終止的,因此您必須知道確切的字段長度? –

回答

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和問號,這將包含不能轉換的字符ANSI的UTF16(NTFS)文件名的只是結果。如果沒有可能的轉換,wcstombs返回一個錯誤,QDebug將任何不可轉換的字符轉換爲?

如果wcstombs遇到寬字符,它不能轉換爲多字節字符,它返回-1強制轉換爲鍵入size_t並將errno設置爲EILSEQ。

因此,如果您需要支持unicode文件名,請不要將它們轉換爲ANSI,並使用支持unicode的函數完全處理它們。

+0

謝謝你這個詳細的答案我很感激它,我修復了非空終止的問題,我試試這個'size_t FileNameLength = pFileNotify-> FileNameLength/sizeof(WCHAR); QByteArray encodedString = QString :: fromWCharArray(pFileNotify-> FileName,FileNameLength).toLatin1(); QTextCodec * codec = QTextCodec :: codecForName(「UTF-8」); QString Fname = codec-> toUnicode(encodedString);'但徒勞無功,而你的意思是_do沒有將它們轉換爲ANSI,並且只使用支持unicode._函數的函數來處理它們。 – Oumaya

+0

@oumaya我的意思是:將文件名保留爲unicode,不要將其轉換爲ansi。如果您需要打開文件,請使用CreateFileW等。讓QT處理unicode字符串(不要將其轉換爲latin1)。我沒有使用QT,但我認爲如果GUI需要顯示unicode字符串(可能甚至是QString),則必須使用_UNICODE編譯應用程序。長話短說:FILE_NOTIFY_INFORMATION不是問題。這是你輸出字符串的方式。 [如何使用Qt打印Unicode字符?](http://stackoverflow.com/questions/9230610/how-to-print-unicode-characters-using-qt) –

+0

好,但我需要輸出名稱,所以我會嘗試要使用CreateFileW而不是fopen來打開我的文件並查看我能做些什麼來正確地獲取名稱,再次感謝您。 – Oumaya