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

Windows平台Qt6中UTF8与GBK文本编码互相转换、理解文本编码本质

快速答案

  1. UTF8转GBK
QString utf8_str="中UTF文";
std::string gbk_str(utf8_str.toLocal8Bit().data());
  1. GBK转UTF8
std::string gbk_str_given_by_somewhere="中GBK文";
QString utf8_str=QString::fromLocal8Bit(gbk_str_given_by_somewhere.data());

正文

当你在搜寻【Windows平台Qt6中UTF8与GBK文本编码互相转换】的答案时,你实际上遇到的是【Windows平台Qt6与纯C++的字符串编码转换问题】。
Qt6框架内部默认使用UTF编码,Windows文件路径默认GBK(可以通过[控制面板]-[区域]-[管理]-[更改系统区域设置]-[勾选使用Unicode UTF-8]进行更改,但是截止到当前2023年正如勾选框所说这是Beta版本功能,会导致大量使用硬编码GBK的软件无法运行)。因此Qt本身不存在UTF8与GBK转换问题,Qt应用层输入输出都是UTF8,而纯C++本身不会进行编码转换,Windows系统调用只支持GBK,Windows平台下Qt与纯C++的交互会遇到转换问题,例如打印字符串、打开文件路径等。

1. 文本编码原理

  • 什么是文本编码
    计算机中,所有信息都以二进制形式储存在内存中,文本同样是一堆字节。
    直接抛给让两个人一串字节,两个人可能会理解出不同的文本信息,比如一串字节{0xd6,0xd0,0xce,0xc0},你会认为代表什么文本呢?如果一个人只懂ASCII编码,他查了ASCII表后会认为是[Ö,Ð,Î,À];如果一个人只懂GBK编码,他查了GBK表后会认为是[中,文]。就是因为有这些表,就像二战时的电报一样,一串二进制可以被不同的解密方式解密出不同的语义信息。
    人类能看到的文本被加密(编码)后成为了一串二进制,一串二进制被解密(解码)后成为了人类看到的文本。因此小明用A规则去加密文本得到的二进制,再用B规则去解密得到的文本,必然不是小明当初看到的文本。对应地,文本用UTF编码得到的二进制,再用GBK解码得到的文本基本上是乱码,反之亦然。
  • 计算机如何编码和解码
    编码不用多说,按照用户指定的表将用户输入的文本转换为二进制即可。解码就要麻烦一点了,程序并不知道接收到的一串二进制是什么编码,两种方法,一是硬解码,就像Qt,不管三七二十一直接按照UTF格式解;二是智能判断这个二进制是什么编码,例如vscode里就有这个功能,但是可能有误判问题,所以需要人为确认。

2. 默认下Qt6有意义的操作只支持UTF编码输入

  • 何为有意义?例如
    – QString经常被拿来当作文件路径,QString变量创建时强制解析为UTF;
    – QFile的文件路径用来打开文件,强制解析为UTF;
    – qDebug()要与命令行交互,输入的字符串强制解析为UTF,这就是为什么在只支持GBK的命令终端用qDebug打印GBK文本会出现乱码;
    – QFile写入文件的字符串内容不会被Qt转码,因为文件内容字符串本身是没有意义的,只需要将原来的内容不用转码而直接搬运写入即可。
  • 何为默认?例如以下:
std::string std_str="中文";
QString s1=QString::fromStdString(std_str);
QString s2="中文";
qDebug()<<s1<<s2;

s1和s2的右侧内容均被默认按照UTF解码保存,见下图官方文档所述,用了fromUtf8()。代码中,如果你的cpp文件是GBK编码的,那输出乱码,因为GBK编码的字符串却被Qt默认按照UTF解码了;如果你的cpp文件是UTF编码的,那输出正常的中文,因为UTF编码的字符串被Qt默认按照UTF解码,对的上。等号运算符fromStdString

Qt支持程序员指定的非默认的编码转换,例如以下:

std::string std_str="中文";
QString s=QString::fromLocal8Bit(std_str.data());
qDebug()<<s;

代码做了这些操作:将文本原始字节数组按照Local(本地计算机,Windows默认GBK)的格式转码成UTF,QString再按照UTF格式进行解码,符合Qt的UTF入口要求,输出正常的中文。

3. Qt输出是GBK还是UTF?

Qt在开放给程序员的api层面,是UTF,例如QStringtoStdString()函数输出的就是UTF编码的字符串,官方文档描述见下图,自动用了toUtf8();Qt内部直接与操作系统调用的部分,会自动toLocal操作,例如qDebug(),当它的输入为UTF编码的中文时,可以正确打印中文到只支持GBK的命令终端,这是因为Qt直接调用Windows系统函数时,会根据自动toLocal。
toStdString

4.GBK与UTF8互转的几种方法

  • icu
    跨平台编码转换库,Qt底层有用到这个库。
  • iconv
    Linux平台编码转换库。
  • windows.h
    windows平台专用,使用函数MultiByteToWideChar和WideCharToMultiByte。
  • std::codecvt
    C++标准库实现的编码转换,已经被标记为弃用,不建议使用。
  • Qt toLocal8Bit和fromLocal8Bit
    Qt框架配合自己的数据结构QString等,使用Qt时首选。
  • Qt QStringConvert
    内部调用与toLocal8Bit和fromLocal8Bit一样。
http://www.lryc.cn/news/171196.html

相关文章:

  • 【探索Linux】—— 强大的命令行工具 P.9(进程地址空间)
  • ESP32主板-MoonESP32
  • Python 图片处理笔记
  • SpringCloud Ribbon--负载均衡 原理及应用实例
  • Redis的介绍以及简单使用
  • ad18学习笔记十二:如何把同属性的元器件全部高亮?
  • SpringSecurity 核心过滤器——SecurityContextPersistenceFilter
  • 反转单链表
  • 加速新药问世,药企如何利用云+网的优势?
  • C++中string对象之间比较、char*之间比较
  • MVVM模式理解
  • js常用的数组处理方法
  • [Document]VectoreStoreToDocument开发
  • 【LeetCode-简单题】225. 用队列实现栈
  • 数据预处理方式合集
  • 【前端】jquery获取data-*的属性值
  • GB28181学习(五)——实时视音频点播(信令传输部分)
  • 单例模式(饿汉模式 懒汉模式)与一些特殊类设计
  • 133. 克隆图
  • 交流耐压试验目的
  • 使用 YCSB 和 PE 进行 HBase 性能压力测试
  • 正则表达式相关概念及不可见高度页面的获取
  • 深入学习 Redis - 分布式锁底层实现原理,以及实际应用
  • Hive行转列[一行拆分成多行/一列拆分成多列]
  • TypeScript系列之类型 string
  • 【C++】动态内存管理 ③ ( C++ 对象的动态创建和释放 | new 运算符 为类对象 分配内存 | delete 运算符 释放对象内存 )
  • AMS爆炸来袭,上线即巅峰
  • 是面试官放水,还是公司实在是太缺人?这都没挂,华为原来这么容易进...
  • 怒刷LeetCode的第2天(Java版)
  • AUTOSAR汽车电子嵌入式编程精讲300篇-车载CAN总线网络的异常检测(续)