多读几篇,每篇取几句精华加深我对QString的理解。

------------------------------------------------------------------

QString内部仍采用UTF-16存储数据且不会改变,但它读char*的时候(C++语言里最常见的形式,特别对于const来说是这样),默认按照latin1来解读字符串,这就造成乱码。

QString的成员函数知道按照何种编码来处理 C 字符串
QString QString::fromAscii ( const char * str, int size = -1 )
QString QString::fromLatin1 ( const char * str, int size = -1 )
QString QString::fromLocal8Bit ( const char * str, int size = -1 )
QString QString::fromUtf8 ( const char * str, int size = -1 )
单QString 只提供了这几个成员函数,远远满足不了大家的需求,比如,在简体中文Windows下,local8Bit是GBK,可是有一个char串是 BIG5 或 Latin-2怎么办?
那就动用强大的QTextCodec吧,首先QTextCodec肯定知道自己所负责的编码的,然后你把一个char串送给它,它就能正确将其转成Unicode了。
QString QTextCodec::toUnicode ( const char * chars ) const

可是这个调用太麻烦了,我就想直接

QString a= str;

QString a(str);

这样用怎么办?

这样一来肯定没办法同时告诉 QString 你的str是何种编码了,只能通过其他方式了。这也就是开头提到的

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

设置QString默认采用的编码。而究竟采用哪一个,一般来说就是源代码是GBK,就用GBK,源代码是UTF-8就用UTF-8。但有一个例外,如果你保存成了带BOM的UTF-8而且用的微软的cl编译器,此时仍是GBK。

一句话,读中文路径以及写入XML都容易,几乎什么都不用设置。唯独源代码里的中文要千万小心才能正确解析,如下:
QTextCodec *ttt = QTextCodec::codecForName("GBK"); // 上面什么都不写,只写这句就已经够了。
writer.writeTextElement("Chinese5",ttt->toUnicode("中国")); //

参考:

http://hi.baidu.com/dbzhang800/item/431f800fcb653e6dd55a1142
http://www.360doc.com/content/12/0511/18/6828497_210377394.shtml

------------------------------------------------------------------

  • 万恶的MSVC?

  • 注意:如果你在使用msvc的编译器,除了前面提到的东西,你还需要知道一点:

    • 如果你的源码文件是带BOM的utf8,utf16等编码格式,它会有转码的动作。
    • 这样一来,tr()包住的字符串将转码成时GBK、BIG5等system编码,与源文件所用的编码不同。
    • 所以,对此,我们还需要指定源文件的编码:
    CODECFORTR = GB2312
    CODECFORSRC = UTF-8

http://blog.csdn.net/dbzhang800/article/details/7325698
http://blog.csdn.net/dbzhang800/article/details/7540905

------------------------------------------------------------------

在Qt5中,这个问题终于不复存在了,因为

这两个函数

QTextCodec::setCodecForTr(...)
QTextCodec::setCodecForCStrings(...)

被直接去掉了。

这样一来,受影响的直接是如下代码了:

QString s1 = "我是中文";
QString s2("我是中文");
QString s3 = QObject::tr("我是中文")
  • 坏消息

现在Qt5中尽管去掉了setCodecXXX这两个函数,但是默认编码还是latin1。如果你要想使用

"我是中文"

这样的字符串,必须自己使用QTextCodec或这QString::fromXXX 这种东西进行转换

  • 好消息 是:

Qt5发布之时,默认将会是utf8编码,完全可以将你从Qt编码问题解放出来。

  • 坏消息,如果使用的是 MSVC2005/2008/2010,可能无法使用utf8编码,于是

下面的代码

QString s1 = "我是中文";
QString s2("我是中文");
QString s3 = QObject::tr("我是中文")

将不会工作。

  • 因为从MSVC2005起,你无法给编译器设置字符串要使用的编码。尽管2003之前,也无法设置,但是它会遵循源码文件的编码。而2005就自作聪明了,即使你源码文件保存成不带BOM的utf8,它都会试图帮你转换一下。
  • 好消息是什么呢?

如果你在Windows下,且使用的是MinGW,那么只要你将源码文件保存成utf8,前面的代码将直接可以工作(无须其他设置)

如果你在其他平台了,那么应该都默认是utf8文件。同样无须进行设置。

http://blog.csdn.net/dbzhang800/article/details/7325698

------------------------------------------------------------------

没有了setCodecXXX的Qt5

  • Qt5假定的执行字符集是UTF8,不再允许用户擅自改动。这样一来,Qt4中setCodecXXX的各种副作用不再存在,而且中文问题更为简单。

QString s1 = "汉语";
QString s2("漢語");
QString s3 = tr("中文")
QString s4 = QStringLiteral("中文");//只要字符串不需要翻译,请关注这个
QString s5 = QString::fromWCharArray(L"中文");
QString s6 = u8"中文";//C++11
QString s7 = tr(u8"中文")
...

所有这些在Qt5默认都会正常工作,唯一要求就是:确保你的C++的执行字符集(the execution character set)是UTF-8

http://blog.csdn.net/dbzhang800/article/details/7542672

------------------------------------------------------------------

QtCreator对这个问题好像都是用转义编码来解决的:
在控件上写入中文“退出”,然后查看其自动生成的.h文件中会发现对于非ascii字符都采用了转义编码,像这样
actionExit->setText(QApplication::translate("MainWindow", "\351\200\200\345\207\272", 0));

刚发完贴就找到方法了,可以用utf-8的16进制方式表示常量字符
如果硬要在源码中使用非英文字符串的话,简单符合官方推荐的办法还是使用转义字符来描述了
所以自己写了一个小工具方便的进行转换
http://bbs.csdn.net/topics/390491128
http://download.csdn.net/detail/aqtata/5596247
将UTF-8字符串转换为Latin1编码,比如中文“你好”转换为“\xE4\xBD\xA0\xE5\xA5\xBD”

------------------------------------------------------------------

源码必须是UTF-8,QString需要它
在Qt5中,我们将把QString的8位(8-bit)成员函数的默认编码从Latin 1改为UTF-8。
我建议使用QLatin1String来封装这些字符串,尤其是你正将它们用于一个有QLain1String重载的QString的函数。

你要么用UTF-8重写你的代码,要么你需要用合适的QLatin1String或QTextCodec::toUnicode函数来封装这些字符串。我比较建议使用前一个选项:在你的源代码中使用UTF-8。

http://blog.qt.digia.com/cn/2012/05/16/source-code-must-be-utf-8-and-qstring-wants-it/

------------------------------------------------------------------

直接在代码中使用中文字符串,在Windows下无论用QCreator还是Visual Studio 都会出现中文字符串显示乱码问题
原因是QString默认使用Ascii编码,要手动加入代码
“QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale())”才能解决问题
为什么Qt不默认就是使用QTextCodec::codecForLocale呢?这对各个国家都没有冲突啊

呵呵,如果这样做,Qt岂不是知道倒退了10多年? 你提到这个是10多年前的做法吧,直接导致同一个程序无法跨平台了。在utf8盛行的时代,而VC6/7/8/9/…,默认采用locale字符集,也算是与时代有些格格不入了。
http://qt-project.org/forums/viewthread/19144

------------------------------------------------------------------

QT中的QString内容使用Unicode作为文本编码。但是实际系统中通常采用的是其他编码,例如GBK,utf8等。为了便于兼容这些格式,QT中还设置了两个字符串类型:
QCString类: C类型字符串,必须以0结尾,也就是中间不能含有0. 例如GBK编码的字符串
QByteArray类: 中间可以含有0.例如utf8编码的字符串

注:通过测试,发现Delphi的String可以存储中间为0的字符串

此外,为了对某些分块的字符串(例如从网络中获得的字符串片段)进行编码转换,QT还提供了一个QTextDecoder的辅助类,可以帮助对这类字符串进行解码。
QTextCodec *codec = QTextCodec::codecForName("Shift-JIS");
QTextDecoder *decoder = codec->makeDecoder();
QString string;
while (new_data_available()) {
QByteArray chunk = get_new_data();
string += decoder->toUnicode(chunk);
}

http://blog.sina.com.cn/s/blog_a401a1ea0101fh3z.html

-------------------------------------------------------------------

解决读取ini文件中中文乱码
QSettings settings("xxxx.ini",QSettings::IniFormat);
settings.setIniCodec(QTextCodec::codecForName("GB2312")); //在此添加设置,即可读写ini文件中的中文
settings.beginGroup("company");

解决读取中文文件中文的乱码
QFile file("xxxx.txt");
QTextStream stream(file,QIODevice::ReadOnly);
stream.setCodeC( QTextCodec::codecForName("GB2312") );
stream.readAll();

QString够绕的,分为存储(编译器)和解码(运行期),还有VS编译器的自作主张,还有QT5的变化的更多相关文章

  1. QString内部仍采用UTF-16存储数据且不会改变(一共10种不同情况下的编码)

    出处:https://blog.qt.io/cn/2012/05/16/source-code-must-be-utf-8-and-qstring-wants-it/ 但是注意,这只是QT运行(Run ...

  2. Ceph 存储集群-低级运维

    低级集群运维包括启动.停止.重启集群内的某个具体守护进程:更改某守护进程或子系统配置:增加或拆除守护进程.低级运维还经常遇到扩展.缩减 Ceph 集群,以及更换老旧.或损坏的硬件. 一.增加/删除 O ...

  3. C编译器剖析PDF文档及UCC编译器162.3

    http://blog.csdn.net/sheisc/article/details/42387857 http://blog.csdn.net/sheisc/article/details/455 ...

  4. 多态在编译器是无法确定引用类型的是哪个子类 可以用 instanceof 在运行期判断

  5. 了解Scala反射

    本篇文章主要让大家理解什么是Scala的反射, 以及反射的分类, 反射的一些术语概念和一些简单的反射例子. 什么是反射 我们知道, Scala是基于JVM的语言, Scala编译器会将Scala代码编 ...

  6. 一篇入门 -- Scala 反射

    本篇文章主要让大家理解什么是Scala的反射, 以及反射的分类, 反射的一些术语概念和一些简单的反射例子. 什么是反射 我们知道, Scala是基于JVM的语言, Scala编译器会将Scala代码编 ...

  7. 图解JVM执行引擎之方法调用

    一.方法调用 方法调用不同于方法执行,方法调用阶段的唯一任务就是确定被调用方法的版本(即调用哪一个方法),暂时还不涉及方法内部的具体运行过程.Class文件的编译过程中不包括传统编译器中的连接步骤,一 ...

  8. 深入理解Java虚拟机--中

    深入理解Java虚拟机--中 第6章 类文件结构 6.2 无关性的基石 无关性的基石:有许多可以运行在各种不同平台上的虚拟机,这些虚拟机都可以载入和执行同一种平台无关的字节码(ByteCode),从而 ...

  9. 《深入理解Java虚拟机》-----第8章 虚拟机字节码执行引擎——Java高级开发必须懂的

    概述 执行引擎是Java虚拟机最核心的组成部分之一.“虚拟机”是一个相对于“物理机”的概念 ,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的,而 ...

随机推荐

  1. C - Fafa and his Company

    Problem description Fafa owns a company that works on huge projects. There are n employees in Fafa's ...

  2. # Nginx常见问题

    try_files的使用 按顺序检查文件是否 存在 location /{ try_files $uri $uri/ /index.php } 解析:在/下寻找$uri,如果没有找到,则去找$uri/ ...

  3. 本地Gradle配置方法,免去长时间的更新同步等待

    通常gradle项目在gradle\wrapper\gradle-wrapper.properties中配置在线gradle: distributionBase=GRADLE_USER_HOME di ...

  4. windows下react-native搭建环境

    第一步:安装Java 1.下载JDK,选择适应自己的机型:官网地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downl ...

  5. poj1328 Radar Installation 区间贪心

    题目大意: 在X轴选择尽量少的点作为圆心,作半径为d的圆.使得这些圆能覆盖所有的点. 思路: 把每个点都转化到X轴上.也就是可以覆盖这个点的圆心的位置的范围[a,b].然后按照每个点对应的a从小到大排 ...

  6. oracle-3种工具使用

    1:原命令行,dos 2:sqlplus,图形界面 3:isqlplus,网页版的.(假如自己机器无法安装oracle,可通过别人ip地址去使用oracle,http://ip:5560/isqlpl ...

  7. openMSP430之Custom linker script

    The use of the -mmcu switch is of course NOT mandatory. It is simply a convenient way to use the pre ...

  8. Visual Studio UI Automation 学习(三)

    昨天了解到UI Automation是微软的.Net Framework框架里的4个DLL文件,可以在Visual studio里写代码时引入引用和引用命名空间.然后去写自动化代码. 今天本来是跟着一 ...

  9. mssql for VSCode Guide

    前言 mssql 出自微软自己的 Visual Studio Code 开源插件,代码托管于 GitHub 上. 不过需要注意的一点是,使用 insert into 语句新增的数据...中文是会乱码的 ...

  10. window 8 电脑操作服务集合(网址)

    如何开启Win8远程桌面 http://jingyan.baidu.com/album/48206aeae06627216ad6b3bf.html?picindex=2 Win8.1用户账户的配置管理 ...