当前位置: 首页 > news >正文

QString 与 字符编码 QTextCodec

为了理解编码,我们要先区分 文件中字符编码 和 程序运行时字符编码 的区别。
文件中字符编码 顾名思义 就是 文字保存在文件中的采用的字符编码方式,可以在IDE中看到
程序运行时字符编码,是编译器读取从源文件中读取到字符串后再按要求做的一次字符编码转换后存入所采用的字符编码,这个字符编码转码过程是编译器编译时发生的,经过编译器生成的obj文件和exe中保存的字符串就是采用编码转换后的字符编码,也是运行时的字符编码,这个编码可能与源文件中不是同一种字符编码。
通过编译器参数finput-charset(gcc编译器)/source-charset(vs编译器)设置输入到编译器的源文件的字符编码,通过便器参数fexec-charset(gcc编译器)/execution-charset(vs编译器)设置目标文件中字符编码。
编译出来的程序 进行 文件读写 操作时 需要做额外操作, 特别是读取文件字节流 放入到QString中 时,需要明确知道文件中的字符编码,然后给与正确的转换。

文件编码和输出显示乱码有兴趣可以参考:qt 汉字输出 显示乱码 解决-CSDN博客


QString中只存放unicode的utf16编码的字符串,内部用QChar(short)类型的内存 进行 保存。

char*变量在内存中存放的字符串默认编码,与编译器参数 execution-charset有关,而vs2015及以下编译器默认为 "/execution-charset=GB2312",也就是char*变量内存中保存时使用ansi(具体为GB2312)编码,vs2022默认为 "/execution-charset=UTF-8",gcc或类gcc编译器默认为 "-fexec-charset=UTF-8",特就是char*使用unicode的utf8编码。可以通过在字符串前加u8强制编译器对某个char*变量在内存中保存时采用unicode的utf8编码。

char*转换成QString,一定会做一次字符编码的转码!!!
通过QString(const char*)构造的QString对象,char*字符串会被QString强制当成unicode的 utf8编码,这是QString代码不可更改的,并隐式的将这个强制当做unicode 的utf8编码的字符串转换成unicode的utf16编码的字符串。vs编译器 的 execution-charset 默认 为ansi编码,存放的编码为ansi编码,如果你qt工程采用vs2015编译器或以下编译器,这时候强制当做unicode的utf8转换成QString,就一定会乱码,(所以这个时候最好设置"/execution-charset=UTF-8"的编译器参数)。QString 官方不建议使用从char*转QString的构造函数。所以在这个构造函数前加了QT_ASCII_CAST_WARN 宏开关和宏提示。
QString中所有的从char*转换到QString的构造函数 或者 由char*隐式转换到QString的函数 或者 参数中含有char*的非static函数 都是隐式调用QString::fromUtf8(char*) 这个静态函数 进行字符编码的转换的。
从QByteArray转QString 与 char*转QString 是一样,也会出现同样的问题

D:\Qt\Qt5.12.0\5.12.0\mingw73_64\include\QtCore\qstring.h
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
.......inline QT_ASCII_CAST_WARN QString(const char *ch): d(fromAscii_helper(ch, ch ? int(strlen(ch)) : -1)){}inline QT_ASCII_CAST_WARN QString(const QByteArray &a): d(fromAscii_helper(a.constData(), qstrnlen(a.constData(), a.size()))){}inline QT_ASCII_CAST_WARN QString &operator=(const char *ch){ return (*this = fromUtf8(ch)); }inline QT_ASCII_CAST_WARN QString &operator=(const QByteArray &a)
......D:\Qt\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\tools\qstring.cpp
......
QString::Data *QString::fromAscii_helper(const char *str, int size)
{QString s = fromUtf8(str, size);s.d->ref.ref();return s.d;
}
......

从char*转到QString ,QString有提供很多的static类型的转码函数,qt建议通过调用这些函数进行显示的编码转换。

D:\Qt\Qt5.12.0\5.12.0\mingw73_64\include\QtCore\qstring.hstatic inline QString fromLatin1(const QByteArray &str)//从ascii编码转unicode的utf16编码{ return str.isNull() ? QString() : fromLatin1(str.data(), qstrnlen(str.constData(), str.size())); }static inline QString fromUtf8(const QByteArray &str)  //从unicode8的编码转换成unicode的utf16编码{ return str.isNull() ? QString() : fromUtf8(str.data(), qstrnlen(str.constData(), str.size())); }static inline QString fromLocal8Bit(const QByteArray &str) //从local编码转换虫unicode的utf16编码{ return str.isNull() ? QString() : fromLocal8Bit(str.data(), qstrnlen(str.constData(), str.size())); }static QString fromUtf16(const ushort *, int size = -1);   //从unicode的utf16编码转unicode的utf16编码,可以在字符串前存放BOM来指定输入的字符串字节序,否则采用系统默认字节序static QString fromUcs4(const uint *, int size = -1);      //从unicode的utf32编码转unicode的utf16编码,可以在字符串前存放BOM来指定输入的字符串字节序,否则采用系统默认字节序
#if defined(Q_COMPILER_UNICODE_STRINGS)static QString fromUtf16(const char16_t *str, int size = -1){ return fromUtf16(reinterpret_cast<const ushort *>(str), size); }static QString fromUcs4(const char32_t *str, int size = -1){ return fromUcs4(reinterpret_cast<const uint *>(str), size); }
#endif

fromutf16()和fromutf32()都可以在字符串前面加入BOM,来明确告诉QString,字节流所采用的字节序(大小端)。否则会被默认当做当前系统所采用的字节序。
下面是fromutf16中自动识别输入的字节流中的BOM,并将输入字节流转换成本地字节序的unicode的utf16编码的过程。

D:\Qt\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\tools\qstring.cpp
.......
QString QString::fromUtf16(const ushort *unicode, int size)
{if (!unicode)return QString();if (size < 0) {size = 0;while (unicode[size] != 0)++size;}return QUtf16::convertToUnicode((const char *)unicode, size*2, 0);
}
........D:\Qt\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\codecs\qutfcodec_p.h
.......
enum DataEndianness
{DetectEndianness,BigEndianness,LittleEndianness
};
.......D:\Qt\Qt5.12.0\5.12.0\msvc2015_64\include\QtCore\qchar.h
......
class Q_CORE_EXPORT QChar {
public:enum SpecialCharacter {.......ByteOrderMark = 0xfeff,ByteOrderSwapped = 0xfffe,
........D:\Qt\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\codecs\qutfcodec.cpp    
........
QString QUtf16::convertToUnicode(const char *chars, int len, QTextCodec::ConverterState *state, DataEndianness e = DetectEndianness)
{DataEndianness endian = e;bool half = false;uchar buf = 0;bool headerdone = false;QChar *qch = (QChar *)result.data();
......while (len--) {if (half) {QChar ch;if (endian == LittleEndianness) {ch.setRow(*chars++);ch.setCell(buf);} else {ch.setRow(buf);ch.setCell(*chars++);}if (!headerdone) {headerdone = true;if (endian == DetectEndianness) {if (ch == QChar::ByteOrderSwapped) {endian = LittleEndianness;} else if (ch == QChar::ByteOrderMark) {endian = BigEndianness;} else {if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {endian = BigEndianness;} else {endian = LittleEndianness;ch = QChar((ch.unicode() >> 8) | ((ch.unicode() & 0xff) << 8));}*qch++ = ch;}} else if (ch != QChar::ByteOrderMark) {*qch++ = ch;}} else {*qch++ = ch;}half = false;} else {buf = *chars++;half = true;}}
......

QTextCodec主要意义之一就是为QString的toLocal8BIt()和fromLocal8Bit(char*)设置字符编码器。QTextCodec可以通过预编译宏开关QT_NO_TEXTCODEC 进行开启或关闭,默认开启。

fromLocal8Bit(char*)需要与QTextCodec结合使用,否则输入的字节流会被当做ascii编码进行处理。fromLocal8Bit(char*)需要通过QTextCodec为QString指定字符编码器,而该字符编码要与编译器所采用的编码保持一致,也就是编译器参数 execution-charset(vs编译器参数) /fexec-charset(gcc编译器)所指定的编码保持一致!!!

QString QString::fromLocal8Bit_helper(const char *str, int size)
{if (!str)return QString();if (size == 0 || (!*str && size < 0)) {QStringDataPtr empty = { Data::allocate(0) };return QString(empty);}
#if !defined(QT_NO_TEXTCODEC)if (size < 0)size = qstrlen(str);QTextCodec *codec = QTextCodec::codecForLocale();  //获取到TextCodec设置的字符编码器if (codec)return codec->toUnicode(str, size);
#endif // !QT_NO_TEXTCODECreturn fromLatin1(str, size);
}

同样的QString 的 toLocal8BIt() 也依赖QTextCodec,qt输出到控制台窗口时,会使用QTextCodec进行字符转码,然后再输出到控制台窗口。具体参考qt 汉字输出 显示乱码 解决-CSDN博客

 简单案例:

#include <QTextCodec>
#include <QDebug>
#include <Windows.h>
int main()
{//QTextCodec编码器要与编译器参数execution-charset(vs编译器,默认为GB2312)/fexec-charset(gcc或类gcc编译器,默认为UTF8)的值一致,QTextCodec *codec=QTextCodec::codecForName("GB2312");   //设置QString的fromLocal8Bit() 和toLocal8Bit()的QTextCodec为GB2312QTextCodec//QTextCodec *codec=QTextCodec::codecForName("UTF-8");  //设置QString的fromLocal8Bit() 和toLocal8Bit()的QTextCodec为UTF-8 QTextCodecQTextCodec::setCodecForLocale(codec);QString s=QString::fromLocal8Bit("你好");//QString s=QString::fromUtf8(u8"你好");  //system("chcp 936");      //设置控制台输出窗口接收GB2312编码的字符串//system("chcp 65001");  //设置控制台输出窗口接收utf8编码的字符串qDebug()<<s<<endl;return 0;
}

相关文章:

QString 与 字符编码 QTextCodec

为了理解编码&#xff0c;我们要先区分 文件中字符编码 和 程序运行时字符编码 的区别。 文件中字符编码 顾名思义 就是 文字保存在文件中的采用的字符编码方式&#xff0c;可以在IDE中看到程序运行时字符编码&#xff0c;是编译器读取从源文件中读取到字符串后再按要求做的一次…...

【STA】SRAM / DDR SDRAM 接口时序约束学习记录

1. SRAM接口 相比于DDR SDRAM&#xff0c;SRAM接口数据与控制信号共享同一时钟。在用户逻辑&#xff08;这里记作DUA&#xff08;Design Under Analysis&#xff09;&#xff09;将数据写到SRAM中去的写周期中&#xff0c;数据和地址从DUA传送到SRAM中&#xff0c;并都在有效时…...

Git的基础使用

几条铁令&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 切换分支前先提交本地的修改代码及时提交&#xff0c;提交过就不会丢遇到任何问题都不要删除文件目录&#xff0c;第一时间找人请教push前和merge前一定要pull保证代码为最新的&#xff0c;有冲突解决冲…...

贪吃蛇(C语言实现)

贪食蛇&#xff08;也叫贪吃蛇&#xff09;是一款经典的小游戏。 —————————————————————— 本博客实现使用C语言在Windows环境的控制台中模拟实现贪吃蛇小游戏。 实行的基本功能&#xff1a; • 贪吃蛇地图的绘制 • 蛇吃食物的功能&#xff08;上、…...

使用 mysqldump 迁移 MySQL 表 OceanBase

使用 mysqldump 迁移 MySQL 表 OceanBase 一、什么是mysqldump二、使用mysqldump导出MySQL数据三、将数据导入到OceanBase四、注意 一、什么是mysqldump mysqldump 是 MySQL 数据库管理系统中的一个工具&#xff0c;用于将数据库中的数据导出为文本文件。它可以将整个数据库、…...

谷粒学院--在线教育实战项目【一】

谷粒学院--在线教育实战项目【一】 一、项目概述1.1.项目来源1.2.功能简介1.3.技术架构 二、Mybatis-Plus概述2.1.简介2.2.特性 三、Mybatis-Plus入门3.1.创建数据库3.2.创建 User 表3.3.初始化一个SpringBoot工程3.4.在Pom文件中引入SpringBoot和Mybatis-Plus相关依赖3.5.第一…...

Power Design【数据库设计】

Power Design【数据库设计】 前言版权推荐Power Design【数据库设计】推荐11. PowerDesigner的使用11.1 开始界面11.2 概念数据模型11.3 物理数据模型11.4 概念模型转为物理模型11.5 物理模型转为概念模型11.6 物理模型导出SQL语句补充:sqlyog导入sql文件 最后 前言 2024-3-11…...

Spring Boot中Excel数据导入导出的高效实现

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…...

采购代购系统独立站,接口采集商品上货

采购代购系统独立站的建设与商品上货接口的采集是一个综合性的项目&#xff0c;涉及前端开发、后端开发、数据库设计以及API接口的对接等多个环节。以下是一个大致的步骤和考虑因素&#xff1a; 一、系统规划与需求分析 明确业务需求&#xff1a;确定代购系统的核心功能&…...

Redis精讲

redis持久化 RDB方式 Redis Database Backup file (redis数据备份文件), 也被叫做redis数据快照. 简单来说就是把内存中的所有数据记录到磁盘中. 快照文件称为RDB文件, 默认是保存在当前运行目录. [rootcentos-zyw ~]# docker exec -it redis redis-cli 127.0.0.1:6379> sav…...

ELFK 分布式日志收集系统

ELFK的组成&#xff1a; Elasticsearch: 它是一个分布式的搜索和分析引擎&#xff0c;它可以用来存储和索引大量的日志数据&#xff0c;并提供强大的搜索和分析功能。 &#xff08;java语言开发&#xff0c;&#xff09;logstash: 是一个用于日志收集&#xff0c;处理和传输的…...

excel批量数据导入时用poi将数据转化成指定实体工具类

1.实现目标 excel进行批量数据导入时&#xff0c;将批量数据转化成指定的实体集合用于数据操作&#xff0c;实现思路&#xff1a;使用注解将属性与表格中的标题进行同名绑定来赋值。 2.代码实现 2.1 目录截图如下 2.2 代码实现 package poi.constants;/*** description: 用…...

【软件工程导论】——软工学绪论及传统软件工程(学习笔记)

&#x1f4d6; 前言&#xff1a;随着软件产业的发展&#xff0c;计算机应用逐步渗透到社会生活的各个角落&#xff0c;使各行各业都发生了很大的变化。这同时也促使人们对软件的品种、数量、功能和质量等提出了越来越高的要求。然而&#xff0c;软件的规模越大、越复杂&#xf…...

C语言编译成库文件的要求

keil编译成库文件 在Keil中&#xff0c;将C语言源文件编译成库文件通常需要进行以下步骤&#xff1a; 创建一个新的Keil项目&#xff0c;并将所需的C语言源文件添加到该项目中。 在项目设置中配置编译选项&#xff0c;确保生成的目标文件符合库文件的标准格式。 编译项目&…...

Python的模块应用和文件I/O

Python 解释 Python是一种高级编程语言&#xff0c;以其简洁、易读和易用而闻名。它是一种通用的、解释型的编程语言&#xff0c;适用于广泛的应用领域&#xff0c;包括软件开发、数据分析、人工智能等。python是一种解释型&#xff0c;面向对象、动态数据类型的高级程序设计…...

设计模式之依赖倒转原则

目录 1、 基本介绍 2、 应用实例 3、 依赖关系传递的三种方式 (1) 接口传递 (2) 构造方法传递 (3) setter方式传递 4、 注意事项和细节 1、 基本介绍 依赖倒转原则(Dependence Inversion Principle)是指&#xff1a; 高层模块不应该依赖低层模块&#xff0c;二者都应该依…...

Springboot启动后想要做某些事可以通过什么方法实现?

在Spring Boot应用中&#xff0c;如果你想在应用启动完成后执行一些特定的操作&#xff08;例如缓存预热&#xff09;&#xff0c;可以实现CommandLineRunner或ApplicationRunner接口。这两个接口都提供了一个run方法&#xff0c;在Spring Boot应用上下文初始化完成后会被自动调…...

网络原理初识(2)

目录 一、协议分层 1、分层的作用 2、OSI七层模型 3、TCP / IP五层&#xff08;或四层&#xff09;模型 4、网络设备所在分层 5、网络分层对应 二、封装和分用 发送过程&#xff08;封装&#xff09; 1、应用层(应用程序) QQ 2、传输层 3、网络层 4、数据链路层 5、物理…...

【C++】每日一题 92 反转链表

给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 class ListNode { public:int val;ListNode* next;ListNode(int _val) {val _val;next nullptr;} };…...

算法D39 | 动态规划2 | 62.不同路径 63. 不同路径 II

今天开始逐渐有 dp的感觉了&#xff0c;题目不多&#xff0c;就两个 不同路径&#xff0c;可以好好研究一下 62.不同路径 本题大家掌握动态规划的方法就可以。 数论方法 有点非主流&#xff0c;很难想到。 代码随想录 视频讲解&#xff1a;动态规划中如何初始化很重要&#x…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...