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
为了理解编码,我们要先区分 文件中字符编码 和 程序运行时字符编码 的区别。 文件中字符编码 顾名思义 就是 文字保存在文件中的采用的字符编码方式,可以在IDE中看到程序运行时字符编码,是编译器读取从源文件中读取到字符串后再按要求做的一次…...
【STA】SRAM / DDR SDRAM 接口时序约束学习记录
1. SRAM接口 相比于DDR SDRAM,SRAM接口数据与控制信号共享同一时钟。在用户逻辑(这里记作DUA(Design Under Analysis))将数据写到SRAM中去的写周期中,数据和地址从DUA传送到SRAM中,并都在有效时…...
Git的基础使用
几条铁令!!!!! 切换分支前先提交本地的修改代码及时提交,提交过就不会丢遇到任何问题都不要删除文件目录,第一时间找人请教push前和merge前一定要pull保证代码为最新的,有冲突解决冲…...
贪吃蛇(C语言实现)
贪食蛇(也叫贪吃蛇)是一款经典的小游戏。 —————————————————————— 本博客实现使用C语言在Windows环境的控制台中模拟实现贪吃蛇小游戏。 实行的基本功能: • 贪吃蛇地图的绘制 • 蛇吃食物的功能(上、…...
使用 mysqldump 迁移 MySQL 表 OceanBase
使用 mysqldump 迁移 MySQL 表 OceanBase 一、什么是mysqldump二、使用mysqldump导出MySQL数据三、将数据导入到OceanBase四、注意 一、什么是mysqldump mysqldump 是 MySQL 数据库管理系统中的一个工具,用于将数据库中的数据导出为文本文件。它可以将整个数据库、…...
谷粒学院--在线教育实战项目【一】
谷粒学院--在线教育实战项目【一】 一、项目概述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数据导入导出的高效实现
🌟 前言 欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍 &#x…...
采购代购系统独立站,接口采集商品上货
采购代购系统独立站的建设与商品上货接口的采集是一个综合性的项目,涉及前端开发、后端开发、数据库设计以及API接口的对接等多个环节。以下是一个大致的步骤和考虑因素: 一、系统规划与需求分析 明确业务需求:确定代购系统的核心功能&…...
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的组成: Elasticsearch: 它是一个分布式的搜索和分析引擎,它可以用来存储和索引大量的日志数据,并提供强大的搜索和分析功能。 (java语言开发,)logstash: 是一个用于日志收集,处理和传输的…...
excel批量数据导入时用poi将数据转化成指定实体工具类
1.实现目标 excel进行批量数据导入时,将批量数据转化成指定的实体集合用于数据操作,实现思路:使用注解将属性与表格中的标题进行同名绑定来赋值。 2.代码实现 2.1 目录截图如下 2.2 代码实现 package poi.constants;/*** description: 用…...
【软件工程导论】——软工学绪论及传统软件工程(学习笔记)
📖 前言:随着软件产业的发展,计算机应用逐步渗透到社会生活的各个角落,使各行各业都发生了很大的变化。这同时也促使人们对软件的品种、数量、功能和质量等提出了越来越高的要求。然而,软件的规模越大、越复杂…...
C语言编译成库文件的要求
keil编译成库文件 在Keil中,将C语言源文件编译成库文件通常需要进行以下步骤: 创建一个新的Keil项目,并将所需的C语言源文件添加到该项目中。 在项目设置中配置编译选项,确保生成的目标文件符合库文件的标准格式。 编译项目&…...
Python的模块应用和文件I/O
Python 解释 Python是一种高级编程语言,以其简洁、易读和易用而闻名。它是一种通用的、解释型的编程语言,适用于广泛的应用领域,包括软件开发、数据分析、人工智能等。python是一种解释型,面向对象、动态数据类型的高级程序设计…...
设计模式之依赖倒转原则
目录 1、 基本介绍 2、 应用实例 3、 依赖关系传递的三种方式 (1) 接口传递 (2) 构造方法传递 (3) setter方式传递 4、 注意事项和细节 1、 基本介绍 依赖倒转原则(Dependence Inversion Principle)是指: 高层模块不应该依赖低层模块,二者都应该依…...
Springboot启动后想要做某些事可以通过什么方法实现?
在Spring Boot应用中,如果你想在应用启动完成后执行一些特定的操作(例如缓存预热),可以实现CommandLineRunner或ApplicationRunner接口。这两个接口都提供了一个run方法,在Spring Boot应用上下文初始化完成后会被自动调…...
网络原理初识(2)
目录 一、协议分层 1、分层的作用 2、OSI七层模型 3、TCP / IP五层(或四层)模型 4、网络设备所在分层 5、网络分层对应 二、封装和分用 发送过程(封装) 1、应用层(应用程序) QQ 2、传输层 3、网络层 4、数据链路层 5、物理…...
【C++】每日一题 92 反转链表
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left < right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。 class ListNode { public:int val;ListNode* next;ListNode(int _val) {val _val;next nullptr;} };…...
算法D39 | 动态规划2 | 62.不同路径 63. 不同路径 II
今天开始逐渐有 dp的感觉了,题目不多,就两个 不同路径,可以好好研究一下 62.不同路径 本题大家掌握动态规划的方法就可以。 数论方法 有点非主流,很难想到。 代码随想录 视频讲解:动态规划中如何初始化很重要&#x…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
电脑桌面太单调,用Python写一个桌面小宠物应用。
下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...
iOS 项目怎么构建稳定性保障机制?一次系统性防错经验分享(含 KeyMob 工具应用)
崩溃、内存飙升、后台任务未释放、页面卡顿、日志丢失——稳定性问题,不一定会立刻崩,但一旦积累,就是“上线后救不回来的代价”。 稳定性保障不是某个工具的功能,而是一套贯穿开发、测试、上线全流程的“观测分析防范”机制。 …...
LTR-381RGB-01RGB+环境光检测应用场景及客户类型主要有哪些?
RGB环境光检测 功能,在应用场景及客户类型: 1. 可应用的儿童玩具类型 (1) 智能互动玩具 功能:通过检测环境光或物体颜色触发互动(如颜色识别积木、光感音乐盒)。 客户参考: LEGO(乐高&#x…...
Java严格模式withResolverStyle解析日期错误及解决方案
在Java中使用DateTimeFormatter并启用严格模式(ResolverStyle.STRICT)时,解析日期字符串"2025-06-01"报错的根本原因是:模式字符串中的年份格式yyyy被解释为YearOfEra(纪元年份),而非…...
[学习笔记]使用git rebase做分支差异化同步
在一个.NET 项目中,使用了Volo.Abp库,但出于某种原因,需要源码调试,因此,使用源码方式集成的项目做了一个分支archive-abp-source 其中引用方式变更操作的提交为:7de53907 后续,在master分支中…...
