【Qt】总体把握文本编码问题
在项目开发中,经常会遇到文本编码问题。文本编码知识非常基础,但对于新手来说,可能需要花费较长的时间去尝试,才能在脑海中建立对编码的正确认知。文本编码原理并不难,难的是在项目实践中掌握正确处理文本编码的方法。本文从项目实践出发,总结了项目中编码处理的相关经验,希望可以帮助基础比较薄弱的同学,快速建立对编码的基本认知,同时减少实际项目中踩坑的几率。
1. 从不同的视角看数据
1.1 计算机最底层视角
从计算机最底层的视角看,计算机中的数据,不管是寄存器中的数据,还是内存中的数据,还是磁盘上的文件数据,都是以0和1的二进制格式存放的。所以,一般在说二进制数据时候,是从计算机最底层的视角而言的。
1.2 计算机应用视角
应用程序处理计算机中的数据时,只有遵循数据创建者对数据格式的约定,对数据进行处理,才能正确提取出文件内容创建者所想要表达的信息。
文件创建者通常使用文件后缀名来标明文件内容格式。常见的文件格式后缀名有:.jpg、.txt、.mp4 等。
处理数据时,是否遵循数据格式约定,完全由应用程序决定,程序认为它是什么格式,就可以以什么格式对数据进行处理。如果使用和约定不一致的格式处理数据,那么从数据中提取出的信息极有可能是混乱的、无用的。例如,使用文本编辑器打开一张图像,最终文本编辑器的显示内容将是一堆乱码,无法阅读。实际项目中文本出现乱码问题也是这个原因。
2. 文本乱码问题分析
2.1 文本编码简介
对世界上所有符号、文字进行编号,产生一张字符表,这个表叫做“字符集”。这样一来,我们可以使用数字编号来表示字符,每个编号占用相同的字节数。因为世界上的字符很多,一般使用32位的无符号整型存储编号,总计大约可以表示42亿种字符。目前通用的字符集是Unicode字符集。
字符集中,有的字符使用频繁,有的字符使用不频繁,使用相同字节长度的数字编号会有些浪费存储空间。改进的存储方案类似于哈夫曼编码:将使用频繁的字符用更少的字节数表示,使用不频繁的字符,用较长的字节数表示。经过优化的存储方式,叫做“文本编码”。
文本有很多种编码格式,如GBK,GB18030,UTF-8等等,目前最常用的文本编码格式是UTF-8。编码的具体实现不是本文的主要内容,所以不作展开。
2.1 文本乱码原因
由于计算机最早由老外发明,所以各种文本编码格式对英文的兼容性最好,所以英文通常不会乱码。而同一个中文汉字,用不同的文本编码格式进行编码后,对应的二进制数据是不同的。反过来,同一段文本数据,使用不同的编码进行文本解码,则会解析出来截然不同的文本内容。
总的来说,文本乱码有两个原因:
- 一段数据本身就不是文本数据,可能是图像数据,也可能是视频数据等非文本类型的数据,如果将其视作文本进行解码,必然会导致乱码。
- 我们编写的应用程序,没有采用正确的文本编码格式对文本数据进行解码,导致输出的文本就会出现严重混乱,即乱码,进而导致程序处理结果偏离预期,出现错误。
2.2 文本乱码的处理思路
根据文本乱码的原因,我们在遇到乱码问题时,需要对以下问题进行排查:
- 检查文本数据的产生、存储、传输过程是否出错;
- 尝试与文本内容提供者核对双方文本编码格式是否一致。
- 尝试猜测文本编码,这种方法不是很可靠,但值得一试。
2.3 Qt对文本编码的处理支持
Qt提供了很多关于文本编码解码的函数及类接口。如下所示:
| 接口 | 说明 |
|---|---|
| QString::fromXXX()系列QString的静态函数 | 如QString::fromLocal8Bit,QString::fromUtf8,QString::fromLatin1等,提供了常用的文本解码接口。解码出来的结果统一为UTF-16编码格式,保存在QString缓冲区中。 |
| QString::toXXX()系列QString的静态函数 | 如QString::toLocal8Bit,QString::toUtf8,QString::toLatin1等,提供了常用的文本编码接口。编码后的文本数据,保存在QByteArray缓冲区中。 |
| QTextCodec类 | 提供了更强大的编码转换功能,可以通过文本编码名称获取对应的文本编解码器。可以实现各种文本编码之间的编码转换。 |
这里必须提一下QByteArray和QString的区别。
| 类型 | 区别 |
|---|---|
| QByteArray | QByteArray中的数据,仅仅是二进制数据,可以把它看作是一个内存区,仅此而已。它用于计算机底层视角下的数据存储。可以根据业务需要,确定数据格式类型后,再进行数据处理。 |
| QString | 存储文本。它用于计算机应用视角下的文本内容存储。QString可直接在界面内容显示、文本信息处理等应用层面使用。 |
项目中,我们通常使用QByteArray缓存获取到的数据。如果确定QByteArray中存储的数据是文本,那么下一步需要确定文本的编码格式,最后,可以使用 QString或QTextCodec提供的文本编码转换接口对其中的数据进行编码转换,最终得到QString。反过来,我们也可以将QString保存成多种文本编码格式,用于保存或传输。
3. 容易出现文本乱码的应用场景
3.1 处理含有中文的文件
当我们读写文本文件时,必须使用协商一致的文本编码。否则会导致读取的数据产生严重乱码,影响程序稳定性,甚至造成严重后果。不管读文件还是写文件,都要考虑文本编码问题。
3.2 含有中文的代码文件乱码
使用Qt+MSVC在Windows上进行开发时,经常会遇到代码编译不通过,或者程序运行出现乱码的问题。原因是MSVC默认认为源代码是GBK编码。在Qt .pro文件中打开以下编译开关,告诉MSVC编译器,使用UTF-8格式处理源码文本即可解决:
QMAKE_C_FLAGS += /utf-8
QMAKE_CXX_FLAGS += /utf-8
3.3 处理含有中文的通信数据
在进行数据通信的时候,如果通信协议中包含中文,而通信双方又没有对文本编码做出明确约定,那么很有可能会出现乱码的问题。解决办法是,通信双方通信协议中提前约定好的统一的文本编码,一般可以使用UTF-8编码。
4. 总结
牢记:只要我们按文本处理数据,就要考虑数据格式和文本编码。绝不可忽略文本编码直接进行文本处理。
除Qt开发外,在其他软件开发技术中也需要注意文本编码问题。
本文主要讲解了文本编码的相关处理经验和总体逻辑框架。文本编码相关内容很多,项目中可能会出现各种各样的问题,需要结合本文讲解的总体思路,深入问题综合分析。
本文原创发布于 Qt未来工程师。
相关文章:
【Qt】总体把握文本编码问题
在项目开发中,经常会遇到文本编码问题。文本编码知识非常基础,但对于新手来说,可能需要花费较长的时间去尝试,才能在脑海中建立对编码的正确认知。文本编码原理并不难,难的是在项目实践中掌握正确处理文本编码的方法。…...
Linux命令(77)之curl
linux命令之curl 1.curl介绍 linux命令之curl是一款强大的http命令行工具,它支持文件的上传和下载,是综合传输工具。 2.curl用法 curl [参数] [url] curl参数 参数说明-C断点续传-o <filename>把输出写到filename文件中-x在给定的端口上使用HT…...
详解 sudo usermod -aG docker majn
这个命令涉及到几个 Linux 系统管理的基础概念,包括 sudo、usermod 和用户组管理。我们可以逐一地解析它们: sudo: sudo(superuser do)允许一个已经被授权的用户以超级用户或其他用户的身份执行一个命令。当使用 sudo 前缀一个命令…...
大数据课程L2——网站流量项目的算法分析数据处理
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解网站流量项目的算法分析; ⚪ 了解网站流量项目的数据处理; 一、项目的算法分析 1. 概述 网站流量统计是改进网站服务的重要手段之一,通过获取用户在网站的行为,可以分析出哪些内…...
jar包或exe程序设置为windows服务
最近在使用java和python制作客户端时突发奇想,是否能够通过一种方法来讲jar包和exe程序打包成windows服务呢?简单了解了一下是可以的。 首先要用到的是winSW,制作windows服务的过程非常简单,仅需几步制作完成,也不需要…...
数据结构--- 树
(一)知识补充 定义 树是一种数据结构,它是由n(n≥0)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。 它具有以下的特点: 每个节点有零个或多个子节点; 没有父节点的节点称为根节点;每一个非根…...
两个pdf文件合并为一个怎么操作?分享pdf合并操作步骤
不管是初入职场的小白,还是久经职场的高手,都必须深入了解pdf,特别是关于pdf的各种操作,如编辑、合并、压缩等操作,其中合并是这么多操作里面必需懂的技能之一,但是很多人还是不知道两个pdf文件合并为一个怎…...
Zookeeper简述
数新网络-让每个人享受数据的价值 官网现已全新升级—欢迎访问! 前 言 ZooKeeper是一个开源的、高可用的、分布式的协调服务,由Apache软件基金会维护。它旨在帮助管理和协调分布式系统和应用程序,提供了一个可靠的平台,用于处理…...
1、Flutter移动端App实战教程【环境配置、模拟器配置】
一、概述 Flutter是Google用以帮助开发者在IOS和Android 两个平台开发高质量原生UI的移动SDK,一份代码可以同时生成IOS和Android两个高性能、高保真的应用程序。 二、渲染机制 之所以说Flutter能够达到可以媲美甚至超越原生的体验,主要在于其拥有高性…...
stride与padding对输出尺寸的计算
公式: 练习: 图1: input4,filter3,padding0,stride1 output2 图2: input5,filter3,padding0,stride2 output2 图3: input6,filter3&am…...
Excel VSTO开发2 -建立Excel VSTO项目
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 2 建立Excel VSTO项目 新建项目,选择Excel 2013和2016 VSTO外接程序。输入项目名称(本示例的项目名称为&am…...
chrome插件:一个基于webpack + react的chrome 插件项目模板
项目结构 $ tree -L 1 . ├── README.md ├── node_modules # npm依赖 ├── package.json # 详细依赖 ├── pnpm-lock.yaml ├── public # 里边包含dist,安装的时候安装这个目录即可 ├── src …...
Vue:组件缓存
组件缓存 keep-alive 文章目录 组件缓存 keep-alive一、keep-alive是什么二、keep-alive优点三、问题四、解决方案五、代码示例 六、回顾一下钩子七、总结 一、keep-alive是什么 keep-alive是Vue中的一个内置组件,会缓存不活动的组件实例。并不会销毁组件ÿ…...
【C++】DICOM医学影像工作站PACS源码
PACS即影像存档与传输系统,是医学影像、数字化图像技术、计算机技术和网络通讯技术相结合的产物,是处理各种医学影像信息的采集、存储、报告、输出、管理、查询的计算机应用程序。 PACS是基于DICOM标准的医学影像管理系统,其模块覆盖了从影像…...
UDP的可靠性传输2
系列文章目录 第一章 UDP的可靠性传输-理论篇(一) 第二章 UDP的可靠性传输-理论篇(二) 文章目录 系列文章目录三、流量控制RTORTT流量控制1.如何控制流量2. 发送方何时在发送数据3.流程图 拥塞控制1.慢启动 总结1.拥塞控制和流量…...
《Java程序设计》实验报告
实验内容:面向对象程序设计 1、定一个名为Person的类,其中含有一个String类型的成员变量name和一个int类型的成员变量age, 分别为这两个变量定义访问方法和修改方法,另外再为该类定义一个名为speak的方法, 在其中输出n…...
数据可视化、BI和数字孪生软件:用途和特点对比
在现代企业和科技领域,数据起着至关重要的作用。为了更好地管理和理解数据,不同类型的软件工具应运而生,其中包括数据可视化软件、BI(Business Intelligence)软件和数字孪生软件。虽然它们都涉及数据,但在功…...
Ros noetic 机器人坐标记录运动路径和发布 实战教程(C)
前言: 承接上一篇博文本文将编写并记录上文中详细的工程项目,用于保存小车的运动路径,生成对应的csv,和加载所保存的路径到实际的Rviz中,本文将开源完整的工程项目,工程结构如下: 工程原码位于文章末尾: 路径存储: waypoint_saver 用于存储 waypoint 的节点 waypo…...
Linux入门之多线程|线程的同步|生产消费模型
文章目录 一、多线程的同步 1.概念 2.条件变量 2.1条件变量概念 2.2条件变量接口 1.条件变量初始化 2.等待条件满足 3.唤醒等待 3.销毁条件变量 2.3条件变量demo 二、生产消费模型 1.生产消费模型 2.基于BlockQueue的生产者消费者模型 3.基于C用条件变量和互斥锁实…...
MATLAB解析和保存ini文件
1. 将ini文件转换成struct结构体 function data ini2struct(filename)fid fopen(filename, r);if fid -1error(Unable to open file %s., filename);enddata struct();section ;while ~feof(fid)line fgetl(fid);line strtrim(line);% 如果是注释行或者空行,…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...
客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...
算法刷题-回溯
今天给大家分享的还是一道关于dfs回溯的问题,对于这类问题大家还是要多刷和总结,总体难度还是偏大。 对于回溯问题有几个关键点: 1.首先对于这类回溯可以节点可以随机选择的问题,要做mian函数中循环调用dfs(i&#x…...
