多读几篇,每篇取几句精华加深我对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. dotnet core 发布配置(测试数据库和正式数据库自动切换)

    一.起源 在进行项目开发时,常常要求开发环境,测试环境及正式环境的分离,并且不同环境运行的参数都是不一样的,比如监听地址,数据库连接信息等.当然我们把配置信息保存到一个文件中,每次发布的时候,可以先修 ...

  2. C# 怎么把类文件如(XXX.cs)转为dll文件

    打开VS2012或2017 ,新建项目,选择  类库(.NET Framework),创建好一个项目 在建好的项目中添加需要转的类文件 然后将项目重新生成后,在项目的Debug下就可以找到对应的dll ...

  3. Java数据类型转换1

    1 如何将字串 String 转换成整数 int? A. 有两个方法: 1). int i = Integer.parseInt([String]); 或 i = Integer.parseInt([ ...

  4. JWPL工具处理维基百科wikipedia数据用于NLP

    JWPL处理维基百科数据用于NLP 处理zhwiki JWPL是一个Wikipedia处理工具,主要功能是将Wikipedia dump的文件经过处理.优化导入mysql数据库,用于NLP过程.以下以 ...

  5. 【SQL】通过rowid查找及删除重复记录

    新建T表如下: SQL> select * from t; X Y ---------- --          1 a          1 a          1 a          2 ...

  6. 多种效果进度指示层效果iOS源码项目

    该源码是一个多种效果进度指示层效果源码案例,源码KVNProgress,KVNProgress提供多种效果的进度指示层,有半透明效果,也支持全屏显示.指示层还高度支持自定义,可以按自己的需求定制.效果 ...

  7. C#屏蔽Alt+F4,解决Alt+F4关闭窗体时对话框NO后,线程不退出问题

    //1.将窗体的属性KeyPrieview设置为true //keypreview属性为true的时候,就可以响应键盘事件v //2.在窗体KeyDown事件中加如下代码 private void F ...

  8. VHDL之concurrent之operators

    Using operators Operators can be used to implement any combinational circuit. However, as will becom ...

  9. js动态操作订单表格

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. PythonOpenCV:MLP用于最近邻搜索

    一:简单C++版本的链接: http://blog.csdn.net/kaka20080622/article/details/9039749 OpenCV的ml模块实现了人工神经网络(Artific ...