qt中文乱码问题

首先呢,声明一下,QString 是不存在中文支持问题的,很多人遇到问题,并不是本身 QString 的问题,而是没有将自己希望的字符串正确赋给QString。

很简单的问题,"我是中文"这样写的时候,它是传统的 char 类型的窄字符串,我们需要的只不过是通过某种方式告诉QString 这四个汉字采用的那种编码。而问题一般都出在很多用户对自己当前的编码没太多概念,

于是

一个简 单的 Qt 程序

 

下面这个小程序,估计大家会感到比较亲切。似乎有相当多的中文用户尝试写过这样的代码:

#include <QtGui/QApplication>
#include <QtGui/QLabel>

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QString a= "我是汉字";
    QLabel label(a);
    label.show();
    return app.exec();
}

编码,保存,编译,运行,一切都很顺利,可是结果呢:

  • 多数用户看到

    其他用户看到

    ÎÒÊǺº×Ö

    æˆ‘æ˜¯æ±‰å —

出乎意料,界面上中文没显示出来,出现了不认识字符。 于是开始用搜索引擎搜索,开始上论坛发帖或抱怨

最后被告知,下面的语句之一可以解决问题:

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

两条指令挨个一试,确实可以解决(多数用户是第一条,其他用户是第二条)。那么,为什么会这样呢?

两种乱码什么时候出现

对这个问题,我想大家可能都有话说。在继续之前,我们先列个表,看看两种乱码分别在那种情况下出现:

我们只列举大家最常用的3个编译器(微软VS的中的cl,Mingw中的g++,Linux下的g++),源代码分别采用GBK 和 不带BOM的UTF-8 以及 带BOM的UTF-8 这3中编码进行保存。

  • 源代码的编码

    编译器

    结果

     

    GBK

    cl

    1

    *

    mingw-g++

    1

    *

    g++

    1

     

    UTF-8(不带BOM)

    cl

    2

     

    mingw-g++

    2

     

    g++

    2

    *

    UTF-8(带BOM)

    cl

    1

     

    mingw-g++

    2

     

    g++

    编译失败

     

采用3种不同编码保存的源代码文件,分别用3种不同的编译器编译,形成9种组合,除掉一种不能工作的情况,两种乱码出现的情况各占一半。

从中我们也可以看出,乱码和操作系统原本是没有关系的。但我们在 Windows 一般用的GBK,linux一般用的是不带BOM的UTF-8。如果我们只考虑带*的情况,也可以说两种乱码和系统有关。

QString 为什么会乱码呢

真的是 QString 乱码了吗?我们可以问问自己,我们抱怨的对象是不是搞错了?

继续之前,先明确几个概念:

明确概念0:

  • "我是汉字" 是C语言中的字符串,它是char型的窄字符串。上面的例子可写为

const char * str = "我是汉字";
QString a= str;

char str[] = "我是汉字";
QString a= str;

明确概念1:

  • 源文件是有编码的,但是这种纯文本文件却不会记录自己采用的编码

这个是问题的根源,不妨做个试验,将前面的源代码保存成GBK编码,用16进制编辑器能看到引号内是ce d2 ca c7 ba ba d7 d6这样8个字节。

现在将该文件拷贝到正体(繁体)中文的Windows中,用记事本打开会什么样子呢?

...
    QString a= "扂岆犖趼";
    QLabel label(a);
    label.show();
...

那么放到欧美人的Windows系统中,再用记事本打开呢?

...
    QString a= "ÎÒÊǺº×Ö";
    QLabel label(a);
    label.show();
...

同一个文件,未做任何修改,但其中的8个字节ce d2 ca c7 ba ba d7 d6,对用GBK的大陆人,用BIG5的港澳台同胞,以及用Latin-1的欧洲人看来,看到的却是完全不同的文字。

明确概念2:

  • 如同我们都了解的'A'与'\x41'等价一样。

GBK编码下的

const char * str = "我是汉字"

等价于

const char * str = "\xce\xd2\xca\xc7\xba\xba\xd7\xd6";

当用UTF-8编码时,等价于

const char * str = "\xe6\x88\x91\xe6\x98\xaf\xe6\xb1\x89\xe5\xad\x97";

注意:这个说法不全对,比如保存成带BOM的UTF-8,用cl编译器时,汉字本身是UTF-8编码,但程序内保存时却是对应的GBK编码。

明确概念3:

  • QString 内部采用的是Unicode。

QString内部采用的是 Unicode,它可以同时存放GBK中的字符"我是汉字",BIG5中的字符"扂岆犖趼" 以及Latin-1中的字符"ÎÒÊǺº×Ö"。

一个问题是,源代码中的这8个字节"\xce\xd2\xca\xc7\xba\xba\xd7\xd6",该怎么转换成Unicode并存到 QString 内?按照GBK、BIG5、Latin-1还是其他方式...

在你不告诉它的情况下,它默认选择了Latin-1,于是8个字符"ÎÒÊǺº×Ö"的unicode码被存进了QString中。最终,8个Latin字符出现在你期盼看到4中文字符的地方,所谓的乱码出现了

QString 工作方式

const char * str = "我是汉字";
QString a= str;

其实很简单的一个问题,当你需要从窄字符串 char* 转成Unicode的QString字符串的,你需要告诉QString你的这串char* 中究竟是什么编码?GBK、BIG5、Latin-1

理想情况就是:将char* 传给QString时,同时告诉QString自己的编码是什么:

就像下面的函数一样,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。

 

总结下,乱码出现的原因主要是:

QString内部采用的是 Unicode,它可以同时存放GBK中的字符"我是汉字",BIG5中的字符"扂岆犖趼" 以及Latin-1中的字符"ÎÒÊǺº×Ö"。

当你需要从窄字符串 char* 转成Unicode的QString字符串的,你需要告诉QString你的这串char* 中究竟是什么编码?GBK、BIG5、Latin-1?

在你不告诉它的情况下,它默认选择了Latin-1,于是8个字符"ÎÒÊǺº×Ö"的unicode码被存进了QString中。最终,8个Latin字符出现在你期盼看到4中文字符的地方,

所谓的乱码出现了。

网上有很多方法介绍直接在main.cpp里设置:

    QTextCodec *codec = QTextCodec::codecForName("UTF-8");

    QTextCodec::setCodecForTr(codec);

    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);

其实这在某些情况下也是有问题的,因为程序可能读到系统的中文路径,或者调用中文路径下的外部程序,这时候如果系统是gb2312就有问题了。

因为中文路径的编码是采用utf-8存到QString里的,系统读中文路径解码的时候采用的却是系统的gb2312,所以会调不起带中文路径的外部程序。

以上问题下面方法可以解决:

    QTextCodec *codec = QTextCodec::codecForName("UTF-8");

    QTextCodec::setCodecForTr(codec);

    QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
    QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());

对于外部字符串编码解码全部采用本地编码。

<think>首先,用户的问题是关于Qt中文乱码的解决方法。我需要参考提供的引用内容来构建回答。引用内容来自多个来源,描述了不同的解决方法。 关键点从引用中提取: - 引用[1]:建议使用QStringLiteral或QString::fromUtf8,以及设置源文件编码为UTF-8。 - 引用[2]:在main函数中使用QTextCodec设置字符编码,包括GBK或UTF-8,具体取决于Qt版本。 - 引用[3]:使用fromLocal8Bit()函数将字符串转换为本地字符集。 - 引用[4]:在main.cpp中设置QTextCodec for Tr, Locale, and CStrings。 - 引用[5]:类似地,在main函数设置QTextCodec for UTF-8。 用户的问题是:"我想解决Qt程序中出现的中文乱码问题 请问Qt 中文乱码 解决方法"。所以,我需要提供一个全面的解决方法。 回答结构: 1. **介绍问题**:简要解释为什么Qt会出现中文乱码(如默认UTF-8 vs Windows本地编码GBK)。 2. **解决方法**:列出几种常见方法,基于引用。 - 方法1:在代码中使用正确的字符串处理函数(如QString::fromUtf8, QStringLiteral)。 - 方法2:在main函数中设置全局字符编码。 - 方法3:设置源文件编码(如#pragma execution_character_set("utf-8"))。 3. **逐步指导**:提供清晰的步骤,帮助用户实施。 4. **推荐方法**:根据引用,推荐使用UTF-8编码,因为它是跨平台的。 5. **相关问题**:生成相关问题,如系统指令要求。 系统指令要求: - 所有行内数学表达式用$...$格式(但这里可能不涉及数学,所以忽略)。 - 独立公式用$$...$$(不适用)。 - LaTeX语法正确(在回答中不需要LaTeX,因为内容是关于编程的)。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾添加引用标识,例如[^1]。 在回答中,我需要自然地引用内容。例如,当提到某个方法时,添加引用标识。 最终回答结构: - 开头:解释问题。 - 主要方法:分点列出。 - 结尾:总结和生成相关问题。 生成相关问题: - 如"如何设置Qt项目的默认编码?" - "Qt中不同版本如何处理中文乱码?" - "为什么在Windows上Qt中文乱码更常见?" 确保回答真实可靠,基于引用。</think>### Qt中文乱码解决方法 在Qt开发中,中文乱码问题通常源于编码不一致。Qt默认使用UTF-8编码,而Windows系统本地编码多为GBK或GB2312,导致字符串显示异常。以下是基于多个可靠来源的解决方法,我将从易到难逐步介绍。关键点包括:在代码中正确处理字符串、全局设置编码,以及源文件配置。实施时,请根据您的Qt版本(如Qt 5.x或6.x)和操作系统调整。 #### 1. **在代码中使用字符串处理函数(推荐简单场景)** 在Qt中,直接使用中文字符串时,应通过特定函数转换编码。这适用于局部字符串处理,无需修改全局设置: - **QString::fromUtf8()**:如果源文件是UTF-8编码(推荐跨平台),使用此函数。例如: ```cpp QString str = QString::fromUtf8("你好世界"); // 推荐UTF-8环境[^1][^5] ``` - **QStringLiteral()**:宏方式,编译时优化,适合常量字符串: ```cpp QString str = QStringLiteral("你好世界"); // 高效,但需确保源文件UTF-8[^1][^3] ``` - **QString::fromLocal8Bit()**:将本地编码(如Windows的GBK)转为UTF-8,适用于混合环境: ```cpp QString str = QString::fromLocal8Bit("你好世界"); // 不推荐长期使用,可能不跨平台[^3][^4] ``` - 避免使用`QString::fromLatin1()`或`QString::fromWCharArray()`,它们在中文环境下易出错[^1]。 此方法简单快捷,但需在每个字符串处手动添加。如果项目中有多处中文,建议结合全局设置。 #### 2. **在main函数中设置全局字符编码(推荐全面解决)** 在应用程序入口(`main.cpp`)中,使用`QTextCodec`设置全局编码。这能确保所有字符串(包括`tr()`函数)正确处理: - **Qt 5.x及以下版本**:需设置多个编解码器: ```cpp #include <QTextCodec> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 设置中文字体(可选) a.setFont(QFont("Microsoft Yahei", 9)); // 判断系统环境:Windows用GBK,Linux/macOS用UTF-8 #if (QT_VERSION <= QT_VERSION_CHECK(5,0,0)) #ifdef Q_OS_WIN QTextCodec *codec = QTextCodec::codecForName("GBK"); #else QTextCodec *codec = QTextCodec::codecForName("UTF-8"); #endif QTextCodec::setCodecForLocale(codec); // 本地编码 QTextCodec::setCodecForCStrings(codec); // C字符串编码 QTextCodec::setCodecForTr(codec); // tr()函数编码 #else // Qt 5.0+ 简化设置 QTextCodec *codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForLocale(codec); // 仅需设置本地编码 #endif // ... 其他初始化代码 return a.exec(); } ``` 此方法兼容性强,但需注意:Qt 6.x已弃用`QTextCodec`,推荐纯UTF-8方案[^2][^4][^5]。 - **Qt 6.x版本**:不再支持`QTextCodec`,应确保源文件为UTF-8,并直接使用`u8`前缀: ```cpp QString str = u8"你好世界"; // C++11语法,推荐[^1] ``` #### 3. **设置源文件编码(预防性措施)** 确保Qt源文件(.cpp/.h)保存为UTF-8格式,并在头文件中添加编译指令: - 在Visual Studio中,设置文件编码:File > Save As > Encoding: UTF-8 with BOM。 - 在代码顶部添加: ```cpp #pragma execution_character_set("utf-8") // 强制编译器使用UTF-8[^1] ``` 这能避免编译器错误解析中文字符,尤其在Windows平台[^1][^3]。 #### 总结建议 - **最佳实践**:优先使用`QString::fromUtf8()`或`u8`前缀,并设置源文件为UTF-8。对于旧项目,在`main.cpp`中全局配置`QTextCodec`。 - **原因分析**:乱码源于编码不匹配(如UTF-8 vs GBK)。统一使用UTF-8可减少问题,尤其在跨平台开发中[^2][^3]。 - **注意事项**:测试时,确保系统区域设置支持中文(如Windows控制面板 > 区域)。如果问题持续,检查外部数据源(如文件或数据库)的编码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值