Qt | QTextCodec类使用详解、GBK和UTF8编码互转、QString的toLocal8bit和toLatin1区别

Qt | QTextCodec类使用详解、GBK和UTF8编码互转、QString的toLocal8bit和toLatin1区别



1、QTextCodec简介及使用

1.1 编码之间的转换

Qt使用Unicode来存储、绘制和操作字符串。

unicode是各个编码格式转换的媒介,以UTF-8转到GBK格式为例,需要先将UTF-8转到UNICODE,在通过unicode转到GBK,反之亦然。

Qt提供了一组QTextCodec类,以帮助将非Unicode格式转换为Unicode格式。您还可以创建自己的编解码器类。

支持的编码包括:

  • Big5
  • Big5-HKSCS
  • CP949
  • EUC-JP
  • EUC-KR
  • GB18030
  • HP-ROMAN8
  • IBM 850
  • IBM 866
  • IBM 874
  • ISO 2022-JP
  • ISO 8859-1 to 10
  • ISO 8859-13 to 16
  • Iscii-Bng, Dev, Gjr, Knd, Mlm, Ori, Pnj, Tlg, and Tml
  • KOI8-R
  • KOI8-U
  • Macintosh
  • Shift-JIS
  • TIS-620
  • TSCII
  • UTF-8
  • UTF-16
  • UTF-16BE
  • UTF-16LE
  • UTF-32
  • UTF-32BE
  • UTF-32LE
  • Windows-1250 to 1258

注:gb18030字符集兼容了gbk字符集,以两个字节表示一个文字。

现在假设有一组GBK格式的数据,需要转为unicode格式字符串,那么可以这样:

    QByteArray encodedString = "...";
    QTextCodec *codec = QTextCodec::codecForName("GBK");
    QString string = codec->toUnicode(encodedString);

同样的,如果现在有一组unicode字符串需要转为GBK码数据,那么就是这样:

    QString string = "...";
    QTextCodec *codec = QTextCodec::codecForName("GBK");
    QByteArray encodedString = codec->fromUnicode(string);

以上为简单的使用,还有一个经常遇到的问题就是Qt在windows和linux下中文显示乱码的问题。

1.2 解决中文显示乱码问题

很多新手直接网上一查就是下面三句解决中文乱码问题:

    QTextCodec* codec = QTextCodec::codecForName("GBK");
    // 或者QTextCodec* codec = QTextCodec::codecForName("gb18030 或 gbk 或 utf8");
    QTextCodec::setCodecForCStrings(codec);  // 在qt5中不存在
    QTextCodec::setCodecForTr(codec);        // 在qt5中不存在
    QTextCodec::setCodecForLocale(codec);

这三个函数的作用如下:

setCodecForCStrings(codec):设置QString用于转换const char*和QByteArrays的编解码器。如果编解码器为0(默认值),QString将采用Latin-1。

setCodecForTr(codec):设置QObject::tr()的编码器。如果codec为0(默认值),tr()将采用Latin-1。

setCodecForLocale(codec):将本地编解码器设置为codec,可以由codecForLocale函数返回。如果c是空指针,则编解码器将重置为默认值。对于一些希望使用自己的机制来设置区域设置的应用程序来说,这个功能会有用。

加上这三句后发现真的解决了中文乱码问题!!(固定系统、固定地区语言设置、固定编译环境)。

但是这么干是不对滴!可能换了个系统还是出问题!

那么这三句到底有何作用?下面就详细说一下。

// 获取编解码器名称
qDebug() << QTextCodec::codecForLocale()->name();  // windows下打印GBK,linux下打印utf8

在编写Qt代码的时候使用中文字符串的时候一般会有这三种形式,分别为const char*这种C格式的字符串、QString()进行构造的形式、tr()进行构造的形式:

    QString s1 = "你好";       // 形式1
    QString s2("你好");        // 形式2
    QString s3 = tr("你好");   // 形式3

setCodecForCStrings就是设置的形式一和形式二所用的编码器。

setCodecForTr就是设置使用tr()函数时的所用的编码器。

在Qt4中,如果你没有使用setCodecForCStrings和setCodecForTr指定编解码的方式,那么就会采用Latin-1格式,也就是ASCII。

此时将<你好>这两个中文汉字传入QString,这两个汉字不存在于Latin-1字符集里,自然是会乱码显示,这就是原因!

到了Qt5中,就把setCodecForCStrings和setCodecForTr给去掉了,并将QString()的构造函数默认调用的是fromUTF8,且Qt Creator的文件编码格式默认为UTF-8。

可以从这里看:工具->选项->文本编辑器

而对于使用VS的用户来说,默认编码或者你设置的编码可能是不是UTF8,所以出现了中文显示乱码的问题!这就是Qt5下中文显示乱码的原因!


2、QString的toLocal8bit和toLatin1

QString的toLocal8bit和toLatin1都可以将QString转化为QByteArray,但是两者的区别在于编码的不同。

  • toLocal8Bit:转为本地8bit编码格式。如果字符串包含本地8位编码不支持的字符,则返回的字节数组未定义。前面说过Qt使用Unicode来存储、绘制和操作字符串,执行。执行toLocal8Bit就相当于将unicode编码的qstring转为了本地编码格式,对于windows系统,本地编码格式为GBK,linux系统为UTF-8。

  • toLatin1:以QByteArray的形式返回字符串的Latin-1表示形式。也就是转为了ASCII编码。如果字符串包含非Latin1字符,则返回的字节数组未定义。这些字符可以被抑制或替换为问号。

下面进行示例演示。

    QString s = "你好";

    qDebug() << s.size();                // 输出2(qt用unicode编码格式组织QString)
    qDebug() << s;

    qDebug() << s.toUtf8().size();       // 输出6(UTF8用三个字符表示一个汉字)
    qDebug() << s.toUtf8();              // 转utf8

    qDebug() << s.toLocal8Bit().size();  // 输出4(window下默认编码格式为GBK,一个GBK汉字占两个字节)
    qDebug() << s.toLocal8Bit();         // 转本地编码,也就是GBK格式

    qDebug() << s.toLatin1().size();     // 输出2
    qDebug() << s.toLatin1();            // 转ASCII格式,由于汉字不存在于ASCII编码中,所以会输出两个问号

程序运行结果:


ends…

猜你喜欢

转载自blog.csdn.net/qq153471503/article/details/128138779