1、背景

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

  1. //only for test

int main(int argc, char *argv[])
{

QCoreApplication a(argc, argv);

  1. if ((argc <= ) || !QFileInfo::exists(argv[]))
  2. {
  3. qDebug() << "argc is " << argc << "; " << "argv[1] is : " << argv[] << "; " << "Set default dir.";
  4. QDir::setCurrent("D:/测试部管理/公司例行会议/研发中心周例会/部门周报表/20141107");
  5. }
  6. else
  7. {
  8. qDebug() << "Set dir: " << argv[];
  9. QDir::setCurrent(argv[]);
  10. }
  1. }
  1. //end test

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

2、问题

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

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

结果输出如下:

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

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

3、追踪和解决

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

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

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

1)实际传入的参数为GBK编码

首先调用Qstring的构造函数,如下:

由图可知,传入的参数argv[]类型为char*,该类型不考虑字符串的编码格式。进一步查看该字符串的内存地址0x012f6f72:

通过工具可以看出,内存中的字符串编码为GBK格式。证据如下:

a)GBK格式字符串对应的二进制内容显示

b)相同GBK格式字符串对应的GBK编码内容显示

由此可知,argv参数在作为char*类型进行传入时,内存中保存的是GBK编码。

2)Qt将传入参数理解为Utf-8编码

在构造函数里调用了fromAscii_helper()函数,如下:

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

注意fromUtf8函数,看起来,Qt是准备将传入的char*字符串参数当作UTF-8格式进行转换后,在内部作为Unicode格式进行使用。果然如此:

  1. static inline QString fromUtf8(const char *str, int size = -)
  2. {
  3. return fromUtf8_helper(str, (str && size == -) ? int(strlen(str)) : size);
  4. }
  1. QString QString::fromUtf8_helper(const char *str, int size)
  2. {
  3. if (!str)
  4. return QString();
  5.  
  6. Q_ASSERT(size != -);
  7. return QUtf8::convertToUnicode(str, size);
  8. }

以上就是Qt对传入字符串的编码转换处理。可以通过2个名字来理解:fromUtf8、convertToUnicode,即将传入的字符串当作UTF-8格式,最终转换为Unicode格式。

3)如何解决

由1)和2)可以看出问题点在于传入参数的字符编码格式和Qt要求的不一致。因此解决的方案是要么调整传入参数的字符编码格式,要么调整Qt的要求。

Qt库不能改,windows记事本字符编码和保存格式也不能改,只能在应用程序中进行修改:帮助Qt识别传入参数的字符编码。如下

  1. int main(int argc, char *argv[])
  2. {
  3. QCoreApplication a(argc, argv);
  4. if ((argc <= ) || !QFileInfo::exists(QString::fromLocal8Bit(argv[1])))
  5. {
  6. qDebug() << "argc is " << argc << "; " << "argv[1] is : " << QString::fromLocal8Bit(argv[]) << "; " << "Set default dir.";
  7. QDir::setCurrent("D:/测试部管理/公司例行会议/研发中心周例会/部门周报表/20141107");
  8. }
  9. else
  10. {
  11. qDebug() << "Set dir: " << QString::fromLocal8Bit(argv[]);
  12. QDir::setCurrent(QString::fromLocal8Bit(argv[]));
  13. }
  14. //
  15. }

注意红色字体代码,将输入字符串作为本地编码进行转换,而不是作为UTF-8编码进行转换;另外,windows默认的本地编码为GBK。输出结果为:

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

ok!

Qt5程序参数包含中文GBK编码的问题的更多相关文章

  1. iOS - 网址、链接、网页地址、下载链接等正则表达式匹配(解决url包含中文不能编码的问题)

    DNS规定,域名中的标号都由英文字母和数字组成,每一个标号不超过63个字符,也不区分大小写字母.标号中除连字符(-)外不能使用其他的标点符号.级别最低的域名写在最左边,而级别最高的域名写在最右边.由多 ...

  2. Sublime Text 2/3如何支持中文GBK编码(亲测实现)

    Sublime Text 2/3如何支持中文GBK编码 听语音 | 浏览:17594 | 更新:2014-03-17 10:52 1 2 3 4 5 分步阅读 Sublime Text默认是只支持UT ...

  3. Python中文GBK编码解决实例

    http://eatsalt.blog.163.com/blog/static/879402662009420508748/ #coding:gbk l=['我'.decode('gbk'),'我'. ...

  4. Sublime Text 2/3如何支持中文GBK编码

    Sublime Text默认是只支持UTF8的编码,所以有些时候,当我们打开GBK文件时候,文件内会出先部分的乱码, 在菜单栏选择"Preferences"-->" ...

  5. 西文字符与中文GBK编码的区别

    一般来讲二者读取的时候西文字符的数值是正,而中文字符的数值是负的,此时读取的是中文字符的前一半,需要再读取一个char类型的数据,在大多数运行环境下这个规则都是用. ps:转自算法竞赛的笔记,要注意在 ...

  6. 各种编码中汉字所占字节数;中文字符集编码Unicode ,gb2312 , cp936 ,GBK,GB18030

    vim settings set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936,latin1set termencoding=utf-8se ...

  7. 中文字符集编码Unicode ,gb2312 , cp936 ,GBK,GB18030

    中文字符集编码Unicode ,gb2312 , cp936 ,GBK,GB18030 cp936是微软自己发布的用在文件系统中的编码方式.而bg2312是中国国家标准.我明白mount -t vfa ...

  8. python print 打印的数据包含中文,打印报错UnicodeDecodeError: 'gbk' codec can't decode bytes in position 459-460: illegal multibyte sequence解决办法

    python 2.7 print 的数据中若包括中文,打印则会报错UnicodeDecodeError: 'gbk' codec can't decode bytes in position 459- ...

  9. mysq查询语句包含中文以及中文乱码,字符集 GBK、GB2312、UTF8的区别

    一.查看mysql 字符集设置情况 使用Navicat for Mysql查看工具,打开命令列界面,输入show variables like '%char%';如下图,查看当前mysql字符集设置情 ...

随机推荐

  1. JQuery基本方法介绍和使用

    1.属性 $("p").addClass(css中定义的样式类型); 给某个元素添加样式 常用于表格鼠标移动效果 $(document).ready(function(){ //& ...

  2. sbt assembly build.sbt content

    // import sbt._ // import sbt.Keys._ // import java.io.File // import AssemblyKeys._ name := "n ...

  3. 判断pc端还是移动,并给移动加上其它的样式文件方法

      所有移动端PC端 按 640 进行排版 body, html { width: %; height: %; overflow: hidden; background-color: #; } bod ...

  4. 使用RMAN备份数据库

    1.1使用控制文件备份全库 1.1.1配置备份路径 1.1.2 RMAN备份全库 1.2使用catalog数据库备份全库 1.2.1配置到远程数据库的TNS 1.2.2创建表空间及设置用户 1.2.3 ...

  5. 关于WebDAV带来的网站潜在安全问题的疑问

    WebDAV:分布式创作和版本控制协议 (Web-based Distributed Authoring and Versioning) 一种基于 HTTP 1.1协议的通信协议.它扩展了HTTP 1 ...

  6. springMVC+spring+hibernate注解上传文件到数据库,下载,多文件上传

    数据库 CREATE TABLE `annex` ( `id` bigint() NOT NULL AUTO_INCREMENT, `realName` varchar() DEFAULT NULL, ...

  7. 手动给控制器添加xib

    UIViewController绑定xib界面可视化,有两种方式: 1.第一种(自动化),在创建控制器时,勾选xib选项. 2.第二种手动创建一个Xib,然后再手动绑定到对应的控制器上

  8. 【转】jquery iframe取得元素与自适应高度

    今天没事来总结一下iframe在jquery中怎么操作的,下面我来给各位介绍jquery 获取iframe子/父页面的元素及iframe在jquery高度自适应实现方法,各位朋友可参考. jquery ...

  9. 【iCore3 双核心板】例程二十六:MODBUS TCP实验——电源监控

    实验指导书及代码包下载: http://pan.baidu.com/s/1pKhxKd9 iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...

  10. Yii源码阅读笔记(二十九)

    动态模型DynamicModel类,用于实现模型内数据验证: namespace yii\base; use yii\validators\Validator; /** * DynamicModel ...