何处开始呢?

一旦在Qt程序中出现latin1字符集以外的字符,几乎大家无一例外的会用到 QTextCodec。

而不少网友不分青红皂白,一旦用到中文,就同时使用下面3条指令(其中textc 取为 gb18030 或 utf8,还有的会选用system)。

QTextCodec::setCodecForCStrings(textc);
QTextCodec::setCodecForTr(textc);
QTextCodec::setCodecForLocale(textc);

可是这3个东西有什么用呢?QTextCodec是做什么用的?

字符串、字节流

在C和C++中,我们一般都是将 "hello world!" 这种称为字符串(窄字符串、C传统字符串、char*字符串...)

但目前来说,当我们提字符串时,一般是一个Unicode字符串,其由一个一个的unicode字符构成;当我们提字节流时,是指一个一个的字节。

或许,我们可以说,ANSI C、C++截止目前只有字节流,而缺乏对字符串的支持。

Qt 为字节流和字符串分别提供了 QByteArray 和 QString 两个类(还有QLatin1String等其他类,但这两个是最主要的)。当我们涉及到IO时,比如读写文件、读写网络socket、控制台(终端)输入 输出、读写串口... 操作的都是字节流,如果我们此时需要的操作的内容是字符串,则需要二者之间的相互转换。

QTextCodec做什么?

在 java、C#、python等语言都内置支持unicode字符串的情况下,C、C++ 一直以来对unicode却没有提供任何直接的支持(尽管有个所谓的宽字符wchar_t,但却不能解决什么问题)。即使是下一代标准(C++0x, C1x),对unicode也只是提供了一部分支持,真...

标准对unicode缺乏支持,各个编译器对编码的支持又严重不一,这对于一个需要unicode字符串而又要夸平台的C++的库Qt来说,还真是一个挑战。Qt为解决这个问题提供了QTextCodec。

QTextCodec 提供的是 字符串 和 字节流 之间的相互转换(也就是字符的编解码)。

为了了解 QTextCodec 究竟是做了什么,我们不妨先定义自己的一个自定义QTextCodec

  • 定义一个类似latin1的单字节的字符集

    • 共 0~255 这256个码位
    • 与latin1相比,只不过是a-z和A-Z都反了一下序
  • 比如,对与字节流"\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x21"
    • 按照latin1来解码,则是 u"hello world!"
    • 按照我们的自定义编码,则是无意义的 u"svool dliow!"
class DbzhangCodec:public QTextCodec
{
public:
DbzhangCodec(){}
~DbzhangCodec(){} QString convertToUnicode(const char *chars, int len, ConverterState *) const
{
if (len <= 0 || chars == 0)
return QString();
QString r(len);
for (int i=0; i<len; ++i) {
if (chars[i] > 'a' && chars[i] < 'z')
r[i] = 'a' + 'z' - chars[i];
else if (chars[i] > 'A' && chars[i] < 'Z')
r[i] = 'A' + 'Z' - chars[i];
else
r[i] = QLatin1Char(chars[i]);
}
return r;
}
QByteArray convertFromUnicode(const QChar *in, int len, ConverterState *) const
{
QByteArray r(len, '?');
for (int i=0; i<len; ++i) {
int u = in[i].unicode();
if (u > 255)
r[i] = '?';
else if (u > 'a' && u < 'z')
r[i] = 'z' - u + 'a';
else if (u > 'A' && u < 'Z')
r[i] = 'Z' - u + 'A';
else
r[i] = u;
}
return r;
} QByteArray name() const {return "dbzhang800";}
QList<QByteArray> aliases() const{return QList<QByteArray>()<<"dbzhang-800";}
int mibEnum() const{return 2011;}
};

这个类主要就是要实现两个函数,一个是字节流到unicode的转换,一个是unicode到字节流的转换。

使用举例

定义了一个自定义的int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTextCodec * codec = new DbzhangCodec; QTextCodec::setCodecForCStrings(codec); qDebug()<<QString("hello world!"); return 0; }

注意:此处使用 new,但却没有相应的 delete。这不会造成内存泄漏,因为Qt创建每一个TextCodec之时都会将其放入到一个QList中,这样当程序退出时,如果该codec

  • 于是,前面的字节流被解码为u"svool dliow!"这样一个unicode字符串
  • qDebug输出该字符串时,需要将其编码成字节流?如何编码?是由 QTextCodec::setCodecForLocale 控制的,默认编码为 system
  • 于是被编码成 "svool dliow!" 这样的字节流输出。

插件

前面自定义了一个codec的文件中多加一个类:

#include <QTextCodecPlugin>
#include <QTextCodec> class DbzhangCodecPlugin : public QTextCodecPlugin
{
public:
DbzhangCodecPlugin() {} QList<QByteArray> names() const {return QList<QByteArray>()<<"dbzhang800";}
QList<QByteArray> aliases() const {return QList<QByteArray>()<<"dbzhang-800";}
QList<int> mibEnums() const {return QList<int>()<<2011;} QTextCodec *createForMib(int mib)
{
return mib == 2011 ? new DbzhangCodec : 0;
} QTextCodec *createForName(const QByteArray & name)
{
if (name == "dbzhang800" || name == "dbzhang-800")
return new DbzhangCodec;
else
return 0;
}
}; Q_EXPORT_PLUGIN2(dbzhangcodec, DbzhangCodecPlugin)

配合一个.pro 文件

TARGET = dbzhangcodec
TEMPLATE = lib
CONFIG += plugin
SOURCES += codecplugin.cpp

然后将生成的动态库放入可执行程序目录下的codecs子目录下。

此时,我们在程序中即可直接使用

    QTextCodec * 

setCodecFor****

这3个东西到底是做什么呢?

QTextCodec::setCodecForCStrings(textc);
QTextCodec::setCodecForTr(textc);
QTextCodec::setCodecForLocale(textc);

3个很简单的东西。字节流 <==> 字符串

setCodecForCStrings

void QTextCodec::setCodecForCStrings ( QTextCodec * codec used by QString to convert to and from const char * and QByteArrays. If the QString 与中文问题 我们介绍过这个东西。它将影响QString中
  • QString ( const char * str )
  • QString ( const QByteArray & ba )

  • QString & append ( const QByteArray & ba )

  • QString & append ( const char * str )

  • bool operator!= ( const QByteArray & other ) const

  • bool operator!= ( const char * other ) const
  • QString & operator= ( const QByteArray & ba )

  • QString & operator= ( const char * str )

  • QString fromAscii ( const char * str, int size = -1 )
  • QString fromAscii ( const char * str, int size = -1 )
  • ...

等和字节流(QByteArray或char*)相关但有没有像fromUtf8等那样指定明确编码的成员函数。

以及QByteArray类中涉及unicode字符串的那些成员函数

  • QByteArray & append ( const QString & str )

  • int indexOf ( const QString & str, int from = 0 ) const

  • bool operator< ( const QString & str ) const

  • ...

setCodecForTr

void QTextCodec::setCodecForTr ( QTextCodec * c ) [static]

Sets the Qt中translate、tr关系 与中文问题 一文中我们过提到了一个问题。

当我们使用

QString QObject::tr ( const char * sourceText, const char * disambiguation = 0, int n = -1 ) [static]

这种函数时,需要将 sourceText 这个字节流转换成一个QString字符串。

如果我们已经加载了翻译文件,那么Qt将把该字节流作为一个key去查找相应的翻译好的字符串。

如果没有加载翻译文件呢?Qt将需要某个setCodecForLocale

void QTextCodec::setCodecForLocale ( QTextCodec * c ) [static]

Set the codec is reset to the default.

This might be needed for some applications that want to use their own mechanism for setting the locale.

这个应该没什么好说的,在绝大多数情况下,我们在代码中应该都用不到这个函数(默认的system应该比我们所能设置的要好)。

  • 当我们从程序的命令行读取参数时int main(int argc, char *argv[])

  • 当我们从往控制台输出内容时qDebug()<<QString(...)

  • 使用 QString::fromLocal8Bit() 与 QString::toLocal8Bit()
  • ...

Qt之QTextCodec乱谈的更多相关文章

  1. 微软ASP.NET技术“乱谈”

    微软ASP.NET技术“乱谈” 2014新年了,顺手写的一点文字,主要谈谈我对当前微软ASP.NET技术的看法,比较随意,大伙儿随便看看吧. 1 当前微软Web平台技术全貌 从2002年发布.NET ...

  2. C++矢量图形库系列(1)——矢量图形库乱谈(转)

    转自:http://blog.sina.com.cn/s/blog_4265e1760100lg03.html 本系列篇章的主要内容是讲解矢量图形库的编译.开发和使用.并不对他们周边的内容做过多的描述 ...

  3. 优测优社区干货精选|老司机乱谈编辑器之神——vim

    文 / 腾讯 吴双 前言 优测小优 有话说: 腾讯优测只有应用测试大神?不不不,我们还有各种研发大牛! *** vim 是一种信仰,我自从2004年有了这个信仰,已经12个年头了.本文介绍了学习vim ...

  4. [转]vnpy乱乱谈 02架构

    vnpy乱乱谈 02架构 转自:http://101.132.65.227/?p=51 听到架构这个词先不要害怕. 其实这部分内容还是挺简单的. 一般而言, 一个交易系统我们可以简单的分成输入, (系 ...

  5. JIT-动态编译与AOT-静态编译:java/ java/ JavaScript/Dart乱谈

    C 和 C++ 之类的编译语言性能远超Java,但是生成的代码只能在有限的几种系统上执行,这就有了Java的存在基础(JVM-跨平台) 早期 Java 运行时所提供的性能级别远低于 C 和 C++ 之 ...

  6. 乱谈Qt事件循环嵌套

    本文旨在说明:QDialog::exec().QMenu::exec()等开启的局部事件循环,易用的背后,还有很多的陷阱... 引子 Qt 是事件驱动的,基本上,每一个Qt程序我们都会通过QCoreA ...

  7. QString 乱谈(1)

    一个月前尝试写了一篇关于QStringLiteral,存盘时MoinMoin罢工了.吸取一点经验,还是写成短篇吧 可是,可是,QString不就是简简单单一个字符串么?能有什么可谈的.真的么... ( ...

  8. [转载]QString 乱谈(3)-Qt5与中文

    原文地址http://blog.csdn.net/dbzhang800/article/details/7542672?reload 两个月前,简单写过QTextCodec中的setCodecForT ...

  9. 小小换行符乱谈(文本文件vs二进制文件)

    使用 C 语言的 fopen 打开文件时,可以指定的 mode 有 12 个,其中 6 个包含  "b" 使用 C++ 的 fstream 打开文件时,可用的模式组合有 24 个( ...

随机推荐

  1. 强制改变IE中的文本模式

    <meta http-equiv="X-UA-Compatible" content="IE=edge" />

  2. android 进程和线程管理

    进程和线程的概念: 进程:程序的运行实例. 线程:cpu调度基本单位. Activity启动的时候,启动一个主线程,两个binder线程. 主线程实如何产生的?ZygoteInit启动,经由一系列调用 ...

  3. hdu 1839 Delay Constrained Maximum Capacity Path

    最短路+二分. 对容量进行二分,因为容量和时间是单调关系的,容量越多,能用的边越少,时间会不变或者增加. 因为直接暴力一个一个容量去算会TLE,所以采用二分. #include<cstdio&g ...

  4. Directed Roads

    Directed Roads 题目链接:http://codeforces.com/contest/711/problem/D dfs 刚开始的时候想歪了,以为同一个连通区域会有多个环,实际上每个点的 ...

  5. Windows上安装MongoDB步骤

    事前准备: 1.在mongoDB官网下载.msi文件,我下的是社区版,下载地址:https://www.mongodb.com/download-center#community 2.点击msi文件安 ...

  6. Maven使用笔记

    Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model), 一组标准插件(生命周期各阶段是绑定插件中的目标来完成项目构建工作) 一个项目生命周期(Proje ...

  7. Apache Kafka开发入门指南(1)

    Apache Kafka可以帮助你解决在发布/订阅架构中遇到消费数百万消息的问题.如今,商业应用.社交应用以及其它类型的应用产生的实时信息在不断增长,这些信息需要以简单的方式快速.可靠地路由到各种类型 ...

  8. php websocket聊天室

    要理解socket就要先理解http和tcp的区别,简单说就是一个是短链,一个是长链,一个是去服务器拉数据,一个是服务器可以主动推数据. 而socket就是应用层与TCP/IP协议族通信的中间软件抽象 ...

  9. 双击td字段,出现编辑文本框(更改之后发送数据请求) jsp

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head ...

  10. poj_1743_Musical Theme(后缀数组)

    题目链接:poj_1743_Musical Theme 题意: 给你一串数字,让你找最长的变化相同不重叠的子串,至少长度为5 题解: 处理数据后用后缀数组加二分答案,然后用height数组check答 ...