zoukankan      html  css  js  c++  java
  • Qt5程序参数包含中文GBK编码的问题

    1、背景

    Qt5程序(WeekReport.exe)的main函数里有如下代码:

    //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

    代码主要的功能是判断传入的目录参数是否有效:如果有效则设置为当前路径,否则设置为默认路径。

    2、问题

    程序编译链接完成后,用批处理脚本进行调用,如下:

    WeekReport.exe "D:/测试部管理/公司例行会议/研发中心周例会/部门周报表/20141117" /f

    结果输出如下:

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

    很显然,程序遇到了Encode编码问题,而且看起来和传入参数的中文字符串有关。

    3、追踪和解决

       好在Qt开源,对代码进行跟踪:

       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个名字来理解:fromUtf8、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!

  • 相关阅读:
    IDEA常用快捷键整理(Mac OS X版本)
    转发与重定向的区别
    关于Navicat远程连接远程服务器的mysql 报错问题
    关于mac 系统如何通过终端 连接linux服务器 并传文件!
    Java中String和byte[]间的转换浅析
    选择排序Java版
    插入排序Java版
    JS知识点
    Excel 函数
    垂直滚动公告板
  • 原文地址:https://www.cnblogs.com/lustforlife/p/4104335.html
Copyright © 2011-2022 走看看