Qt中QFtp獲取帶有中文的文件名稱出現亂碼的解決方法(比較巧妙,toLatin1壓縮掉了QString自動給每個英文字符加上的那些00字節)


今天研究了一下QFtp這個類,發現訪問得到的文件名稱中一旦出現中文,不管怎么轉換編碼格式,最終顯示出來的始終都是亂碼。於是我深入地對這一現象進行了研究。這里先簡單介紹一下我的分析過程:

 

FTP服務器在收到List指令后,會把當前文件夾的所有項目(包括文件夾和文件的名稱,大小,時間,所有者等相關信息)列舉出來並返回給FTP客戶端。曾經在網上看到有人說過這樣一句話:“ftp 在編碼問題上相當笨,笨到對編碼一無所知”。確實,多數FTP服務器在返回這些名稱時采用的文字編碼格式為ANSI。這是一個不太好的格式,英文字符占用一個字節存儲空間,非英文字符占用兩個字節存儲空間,長度不一致。而Qt的默認文本編碼采用的UTF-16(是么?這里不太肯定,反正從實驗得到的數據來看至少是這樣的)。即每個字符占據兩個字節的存儲空間。當QFtp從FTP服務器獲取到當前目錄下的項目信息時,名稱部分直接粗暴地一個個地拆分成了UTF-16格式,並認為這些數據就是UTF-16格式的數據。那么當然不管你如何對其進行轉換,數據本身都是錯的,又怎么會得到正確的中文顯示呢?所以,我們需要對這些數據進行特別的整理。

 

今天先寫到這里,做個記號。過兩天會寫出詳細的解決辦法。

 

項目忙完了,下面貼出解決方法。

 

由於編碼錯誤,我寫了兩個函數用於互相轉換編碼。

 

一個是由正常編碼轉為QFTP上所謂的“亂碼”的:QString _ToSpecialEncoding(const QString &InputStr);

另一個是由QFTP亂碼轉換為正常編碼的:QString _FromSpecialEncoding(const QString &InputStr);

 

需要注意的是,使用這個函數之前,你的應用程序應該在界面上能正常顯示中文。我是這樣來實現的:

首先考慮到代碼跨平台,而且主要在Linux平台下運行。因此特別設置了QtCreator的文件默認編碼為UTF-8。

也就是說工程中的.cpp和.h文件內部字符編碼格式為UTF-8。

然后在工程的main函數中,QApplication app...下一行寫如下代碼:

 

    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf8"));
#ifdef Q_OS_WIN
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("gbk"));
#else
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf8"));
#endif
    QTextCodec::setCodecForTr(QTextCodec::codecForName("utf8"));

 

 

注意,Windows的本地默認編碼為gbk(如果你用的是中文系統),Linux本地默認編碼為UTF-8。

因此要根據不同的操作系統來進行設置。Linux系統和Mac系統的默認編碼都是UTF-8,因此上面的代碼沒有區分這兩個操作系統。

 

 

轉換函數實現:

 

 

[cpp] view plain copy
 
  1. QString FTPCommunicator::_FromSpecialEncoding(const QString &InputStr)  
  2. {  
  3. #ifdef Q_OS_WIN  
  4.     return  QString::fromLocal8Bit(InputStr.toLatin1());  
  5. #else  
  6.     QTextCodec *codec = QTextCodec::codecForName("gbk");  
  7.     if (codec)  
  8.     {  
  9.         return codec->toUnicode(InputStr.toLatin1());  
  10.     }  
  11.     else  
  12.     {  
  13.         return QString("");  
  14.     }  
  15. #endif  
  16. }  

  

 

 

 

 

[cpp]  view plain  copy
 
  1. QString FTPCommunicator::_ToSpecialEncoding(const QString &InputStr)  
  2. {  
  3. #ifdef Q_OS_WIN  
  4.     return QString::fromLatin1(InputStr.toLocal8Bit());  
  5. #else  
  6.     QTextCodec *codec= QTextCodec::codecForName("gbk");  
  7.     if (codec)  
  8.     {  
  9.         return QString::fromLatin1(codec->fromUnicode(InputStr));  
  10.     }  
  11.     else  
  12.     {  
  13.         return QString("");  
  14.     }  
  15. #endif  
  16. }  

 

 

當使用QFTP的put方法上傳的時候,目標文件名參數的位置使用_ToSpecialEncoding(正常編碼的字符串);

當使用QFTP的get方法下載的時候,目標文件名參數位置也使用上述函數

當使用QFTP遍歷到的文件作為本地文件名時須使用_FromSpecialEncoding(錯誤編碼的字符串);

 

 

使用環境:

Windows XP SP3 + IIS 作為FTP服務器。

下載程序運行在Windows XP SP3 和 Ubuntu 10.10。兩操作系統均測試通過。若使用其他FTP服務器,設置使用ASCII編碼的也可通過。

http://blog.csdn.net/chaijunkun/article/details/6293107


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM