Chinaunix首页 | 论坛 | 博客
  • 博客访问: 295866
  • 博文数量: 32
  • 博客积分: 665
  • 博客等级: 上士
  • 技术积分: 370
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-25 11:20
文章分类

全部博文(32)

文章存档

2023年(1)

2021年(1)

2020年(2)

2018年(3)

2014年(1)

2013年(2)

2012年(9)

2011年(9)

2010年(2)

2009年(2)

分类: C/C++

2014-02-10 13:42:05


  • 首先说明下源代码文件(.c .cpp)本身的编码:
现在对于中文程序员,一般最常见就有两种编码方式一个是GBK,一个是UTF-8。
在windows环境中,有一个所谓的BOM的。如果文件是值0xEF 0xBB 0xBF开头,则这个BOM可以说明该文本文件是一个UTF-8编码的文件。

  • 如果使用的是MinGW编译器的话:
假如源代码文件是一个GBK编码的文件。则
char a[100] = "中文";
会导致a数组中的值是 D6 D0 CE C4 ... 这就是GBK的"中文"二字的编码。
假如源代码文件是一个UTF-8编码的文件。则
char a[100] = "中文";
会导致a数组中的值是 E4 B8 AD E6 96 87 ... 这就是UTF-8的"中文"二字的编码。

  • 如果使用的是VS 2008一系列的编译器的话:
编译器会检查文件编码,如果是UTF-8的话,他会把这个源代码文件转换编码为GBK后再编译。
也就是说源代码文件是一个UTF-8编码的文件。则
char a[100] = "中文";
一样会导致a数组中的值是 D6 D0 CE C4 ... 即GBK的编码。
这一点很诡异,不知vs做这个转码的原因,网上说是VS 2005之后的版本具有此特性。在编译参数中附加 \utf-8 即可明确指定源代码文件是utf-8编码,告知编译器不需要转码。

  • 乱码的根源(错误型乱码)
QString 内含内部编码(是Unicode也是UTF-16),由于涵盖比较全面的各种字符,是一个全能表示的编码类型,因此被QT选为官方字符表示。可以由其他各种语言的编码转换而来,同时也可以转到其他各种语言的编码,使用一个对应编码的codec即可。


QTextCodec* gbk = QTextCodec::codecForName("GBK");
QTextCodec* utf8 = QTextCodec::codecForName("UTF-8");

codec可以把QString转换为自己的编码:
QByteArray ba = gbk->fromUnicode(QString);
char* c = ba.data();
codec也可以把外来的数据按自己的编码进行解码并转换成统一编码的QString
QString s = gbk->toUnicode(char*);
总之乱码的根源就是以下两种可能的错误,第一种是输入时没有用正确的codec对数据源解码,第二种是输出时没有用正确的codec编码

非错误型乱码
一些操作系统是带有特定语言版本的,对外文的处理一般需要打好外文补丁,包括字符编码表和显示用的字体库等,如果没有打全补丁,则会出现显示乱码,但实际编码是正确的,仅仅是没有字体库导致。这种情况无需修正程序,给操作系统补充该语言的字体即可。

针对于QT4:
构造QString时需注意,如下书写形式:
QString("中文");
时,会根据全局设定函数
QTextCodec::setCodecForCStrings(QTextCodec* codec);
所设定的codec对引号内的数据进行解码。
QObject::tr("中文");
时,会根据全局设定函数
QTextCodec::setCodecForTr(QTextCodec* codec);
所设定的codec对引号内的数据进行解码。

针对于QT5:
取消了以下两个全局设定函数
QTextCodec::setCodecForCStrings(QTextCodec* codec);
QTextCodec::setCodecForTr(QTextCodec* codec);
内部默认为UTF-8解码,也就是说等效于内部调用了
QTextCodec* utf8 = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForCStrings(utf8);
QTextCodec::setCodecForTr(utf8);
这样一来,就要求外部引入的文本,都需要明确的utf8编码进入QString,比如源代码里的QString("中文"),源代码文件是utf8编码,这样就可以了,再比如读了一个文件或由通信方式接收,这个内容实际是GBK编码,就必须这样才行
QTextCodec* gbk = QTextCodec::codecForName("GBK");
QString s = gbk->toUnicode(char* readbuff);

关于locale:
这个概念是stdc++库的,指明了本地系统的地理和语言区域,用于支持国际化的程序判定locale后采取预期的行为,比如正确的语言显示和推送内容等。这个locale可由环境变量而来或可以按需设定
LANG=zh_CN
std::locale::setlocale()
因此对于应用程序是活的。locale是启动时根据运行环境设定好的,如没有特别需要最好不要修改。
对于QT而言,启动后会为系统locale选择合适的文本codec,无需再设定。比如想在console输入或输出一个特定语言的QString的话:
printf("%s\n", QString.toLocal8Bit().data()); // 不必考虑console的显示,会根据locale正确选择
scanf(buff); QString.fromLocal8Bit(buff); // 不必考虑console的编码,会根据locale正确选择

如果显示调用了
QTextCodec::setCodecForLocale(QTextCodec* codec);
这样就设定了指定的codec,此种情形效果是:在任何不知locale是什么的环境中,使用指定的文本codec。
QString::toLocal8Bit();
QString::fromLocal8Bit(char*);
使用的codec就变成了setCodecForLocale指定的codec。

阅读(5682) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~