Qt5程序參數包含中文GBK編碼的問題

一、背景html

Qt5程序(WeekReport.exe)的main函數裏有以下代碼:windows

//only for test

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);函數

    if ((argc <= 1) || !QFileInfo::exists(argv[1]))
    {
        qDebug() << "argc is " << argc << "; " << "argv[1] is : " << argv[1] << "; "   << "Set default dir.";
        QDir::setCurrent("D:/測試部管理/公司例行會議/研發中心周例會/部門週報表/20141107");
    }
    else 
    {
        qDebug() << "Set dir: " << argv[1];
        QDir::setCurrent(argv[1]);
    }
}
//end test

代碼主要的功能是判斷傳入的目錄參數是否有效:若是有效則設置爲當前路徑,不然設置爲默認路徑。工具

二、問題測試

程序編譯連接完成後,用批處理腳本進行調用,以下:字體

WeekReport.exe "D:/測試部管理/公司例行會議/研發中心周例會/部門週報表/20141117" /f

 

結果輸出以下:編碼

argc is  3 ;  argv[1] is :  D:/?????????/??????л???/?з???????????/?????????/20
141117 ;  Set default dir.

很顯然,程序遇到了Encode編碼問題,並且看起來和傳入參數的中文字符串有關。spa

三、追蹤和解決code

   好在Qt開源,對代碼進行跟蹤:htm

   if ((argc <= 1) || !QFileInfo::exists(argv[1]))

   exists的原型爲: bool QFileInfo::exists(const QString & file) [static]

   1)實際傳入的參數爲GBK編碼

   首先調用Qstring的構造函數,以下:

        image

    由圖可知,傳入的參數argv[]類型爲char*,該類型不考慮字符串的編碼格式。進一步查看該字符串的內存地址0x012f6f72:

        image

   經過工具能夠看出,內存中的字符串編碼爲GBK格式。證據以下:

       a)GBK格式字符串對應的二進制內容顯示

        image

        b)相同GBK格式字符串對應的GBK編碼內容顯示

        image

     由此可知,argv參數在做爲char*類型進行傳入時,內存中保存的是GBK編碼。

  2)Qt將傳入參數理解爲Utf-8編碼

在構造函數裏調用了fromAscii_helper()函數,以下:

QString::Data *QString::fromAscii_helper(const char *str, int size)
{
    QString s = fromUtf8(str, size);
    s.d->ref.ref();
    return s.d;
}

注意fromUtf8函數,看起來,Qt是準備將傳入的char*字符串參數看成UTF-8格式進行轉換後,在內部做爲Unicode格式進行使用。果真如此:

static inline QString fromUtf8(const char *str, int size = -1)
    {
        return fromUtf8_helper(str, (str && size == -1) ? int(strlen(str)) : size);
    }
QString QString::fromUtf8_helper(const char *str, int size)
{
    if (!str)
        return QString();

    Q_ASSERT(size != -1);
    return QUtf8::convertToUnicode(str, size);
}

以上就是Qt對傳入字符串的編碼轉換處理。能夠經過2個名字來理解:fromUtf八、convertToUnicode,即將傳入的字符串看成UTF-8格式,最終轉換爲Unicode格式。

  3)如何解決

由1)和2)能夠看出問題點在於傳入參數的字符編碼格式和Qt要求的不一致。所以解決的方案是要麼調整傳入參數的字符編碼格式,要麼調整Qt的要求。

Qt庫不能改,windows記事本字符編碼和保存格式也不能改,只能在應用程序中進行修改:幫助Qt識別傳入參數的字符編碼。以下

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    if ((argc <= 1) || !QFileInfo::exists(QString::fromLocal8Bit(argv[1])))
    {
        qDebug() << "argc is " << argc << "; " << "argv[1] is : " << QString::fromLocal8Bit(argv[1]) << "; "   << "Set default dir.";
        QDir::setCurrent("D:/測試部管理/公司例行會議/研發中心周例會/部門週報表/20141107");
    }
    else 
    {
        qDebug() << "Set dir: " << QString::fromLocal8Bit(argv[1]);
        QDir::setCurrent(QString::fromLocal8Bit(argv[1]));
    }
    //
}

注意紅色字體代碼,將輸入字符串做爲本地編碼進行轉換,而不是做爲UTF-8編碼進行轉換;另外,windows默認的本地編碼爲GBK。輸出結果爲:

Set dir:  "D:/測試部管理/公司例行會議/研發中心周例會/部門週報表/20141117"

ok!

相關文章
相關標籤/搜索