Qt5程序参数包含中文GBK编码的问题
1、背景
Qt5程序(WeekReport.exe)的main函数里有如下代码:
//only for test
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
if ((argc <= ) || !QFileInfo::exists(argv[]))
{
qDebug() << "argc is " << argc << "; " << "argv[1] is : " << argv[] << "; " << "Set default dir.";
QDir::setCurrent("D:/测试部管理/公司例行会议/研发中心周例会/部门周报表/20141107");
}
else
{
qDebug() << "Set dir: " << argv[];
QDir::setCurrent(argv[]);
}
}
//end test
代码主要的功能是判断传入的目录参数是否有效:如果有效则设置为当前路径,否则设置为默认路径。
2、问题
程序编译链接完成后,用批处理脚本进行调用,如下:
WeekReport.exe "D:/测试部管理/公司例行会议/研发中心周例会/部门周报表/20141117" /f
结果输出如下:
argc is ; argv[] is : D:/?????????/??????л???/?з???????????/?????????/
; 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()函数,如下:
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 = -)
{
return fromUtf8_helper(str, (str && size == -) ? int(strlen(str)) : size);
}
QString QString::fromUtf8_helper(const char *str, int size)
{
if (!str)
return QString(); Q_ASSERT(size != -);
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 <= ) || !QFileInfo::exists(QString::fromLocal8Bit(argv[1])))
{
qDebug() << "argc is " << argc << "; " << "argv[1] is : " << QString::fromLocal8Bit(argv[]) << "; " << "Set default dir.";
QDir::setCurrent("D:/测试部管理/公司例行会议/研发中心周例会/部门周报表/20141107");
}
else
{
qDebug() << "Set dir: " << QString::fromLocal8Bit(argv[]);
QDir::setCurrent(QString::fromLocal8Bit(argv[]));
}
//
}
注意红色字体代码,将输入字符串作为本地编码进行转换,而不是作为UTF-8编码进行转换;另外,windows默认的本地编码为GBK。输出结果为:
Set dir: "D:/测试部管理/公司例行会议/研发中心周例会/部门周报表/20141117"
ok!
Qt5程序参数包含中文GBK编码的问题的更多相关文章
- iOS - 网址、链接、网页地址、下载链接等正则表达式匹配(解决url包含中文不能编码的问题)
DNS规定,域名中的标号都由英文字母和数字组成,每一个标号不超过63个字符,也不区分大小写字母.标号中除连字符(-)外不能使用其他的标点符号.级别最低的域名写在最左边,而级别最高的域名写在最右边.由多 ...
- Sublime Text 2/3如何支持中文GBK编码(亲测实现)
Sublime Text 2/3如何支持中文GBK编码 听语音 | 浏览:17594 | 更新:2014-03-17 10:52 1 2 3 4 5 分步阅读 Sublime Text默认是只支持UT ...
- Python中文GBK编码解决实例
http://eatsalt.blog.163.com/blog/static/879402662009420508748/ #coding:gbk l=['我'.decode('gbk'),'我'. ...
- Sublime Text 2/3如何支持中文GBK编码
Sublime Text默认是只支持UTF8的编码,所以有些时候,当我们打开GBK文件时候,文件内会出先部分的乱码, 在菜单栏选择"Preferences"-->" ...
- 西文字符与中文GBK编码的区别
一般来讲二者读取的时候西文字符的数值是正,而中文字符的数值是负的,此时读取的是中文字符的前一半,需要再读取一个char类型的数据,在大多数运行环境下这个规则都是用. ps:转自算法竞赛的笔记,要注意在 ...
- 各种编码中汉字所占字节数;中文字符集编码Unicode ,gb2312 , cp936 ,GBK,GB18030
vim settings set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936,latin1set termencoding=utf-8se ...
- 中文字符集编码Unicode ,gb2312 , cp936 ,GBK,GB18030
中文字符集编码Unicode ,gb2312 , cp936 ,GBK,GB18030 cp936是微软自己发布的用在文件系统中的编码方式.而bg2312是中国国家标准.我明白mount -t vfa ...
- 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- ...
- mysq查询语句包含中文以及中文乱码,字符集 GBK、GB2312、UTF8的区别
一.查看mysql 字符集设置情况 使用Navicat for Mysql查看工具,打开命令列界面,输入show variables like '%char%';如下图,查看当前mysql字符集设置情 ...
随机推荐
- android-Activity(四大组件之一)
一.Activity理解 1.定义: 直译为活动,是Android定义四大应用组件之一,也是最重要的用的最多的: 用来提供一个能让用户操作并与之交互的界面 一个应用有多个界面也就是包含多个Activi ...
- WordPress插件入口菜单创建的位置代码
Add_management_page() 在Tools下面创建 Add_options_page() 在Settings下面创建 Add_theme_page() 在Appearance下面创建 A ...
- 最实用的IT类网站及工具大集合[转]
1.聚合数据 大家在开发过程中,可能会用到各种各样的数据,想找一些接口来提供一些数据.比如天气预报查询,火车时刻表查询,彩票查询,身份证查询等等.有了这个接口,直接调用即可.各种各样的API接口满足你 ...
- javascript:正则大全
:replace函数,为写自己的js模板做准备 待完善 function 1,声明&用法 //数组: var arr=[];//字面量 var arr=new Array();//构造函数 / ...
- 实现服务器端与客户端的高频实时通信 SignalR(2)
说明:本篇文章与上篇文章 实现服务器端与客户端的实时通信 SignalR(1) 基本代码类似,只是做了些处理 高频 的改动. 一.本文出处:SignalR 实例介绍 (建议看原著里面有DEMO下载) ...
- shell读取文件每行,并执行命令
#!/bin/bash while read line do $line & done < /path/filename
- VC 菜单前的勾的切换
if (pMenu->GetSubMenu(2)->GetMenuState(ID_STOP_SPOT_OP_MOSUE,MF_BYCOMMAND) == MF_UNCHECKED) { ...
- zepto源码--核心方法5(文本操作)--学习笔记
涉及到文本内容的主要有三个函数:html, text, val. 我们已经见过多次,一个函数多种用途的情况,今天这三个函数也不例外,既可以获取内容,也可以设置内容.判断条件就是有没有传入参数,如果没有 ...
- 《Linux内核设计与实现》CHAPTER5阅读梳理
<Linux内核设计与实现>CHAPTER5阅读梳理 [学习时间:2.5hours] [学习内容:系统调用的概念.功能及实现:系统调用的创建和使用方法] CHAPTER5 系统调用 1.系 ...
- git pull all braches
控制台下执行如下: git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote ...