Unicode字符集和UTF编码

文章目录

  • 前言
  • 一、字符集和编码方式
  • 二、unicode字符集
    • utf32编码
    • utf8编码
      • utf8编码函数示例
      • utf8解码函数示例
    • utf16编码
      • utf16编码解码函数示例
  • 总结


前言

本文详细介绍 u n i c o d e unicode unicode 字符集和其相关的三种编码方式: u t f 8 utf8 utf8 u t f 16 utf16 utf16 u t f 32 utf32 utf32,并给出一个编码和解码的参考程序。

一、字符集和编码方式

字符集是一些字符的集合,字符集中每一个字符有一个唯一的字符编码表示该字符,编码方式规定了计算机存储该字符集中字符编码的规则,也是计算机解读一串二进制序列的规则。
1: A S C I I ASCII ASCII 码用 7 b i t ( 0 x 00 − 0 x 7 f ) 7bit \ (0x00-0x7f) 7bit (0x000x7f) 存储英文字符,字符集为 128 128 128 个英文字符,即 A S C I I ASCII ASCII 字符集。 A S C I I ASCII ASCII 码的编码方式类似直接映射,字母 A A A 对应的字符编码是 65 65 65,在 A S C I I ASCII ASCII 编码下为 0 x 41 0x41 0x41。字符编码的值也是 A S C I I ASCII ASCII 码值。
2: A S C I I ASCII ASCII 字符集的缺陷非常直观:只包含英文字符。
3: U n i c o d e Unicode Unicode 是国际标准字符集,它将世界各种语言的每个字符定义一个唯一的字符编码,以满足跨语言、跨平台的文本信息转换。 2023 2023 2023 9 9 9 月发表的 15.1 15.1 15.1 版本中定义了 149813 149813 149813 个字符。规定 U n i c o d e Unicode Unicode 字符编码存储方式的规则主要有三种: u t f 8 utf8 utf8 u t f 16 utf16 utf16 u t f 32 utf32 utf32

二、unicode字符集

U n i c o d e Unicode Unicode 为每一个字符分配一个唯一的字符编码,称为在编码空间中的一个码点 ( c o d e p o i n t ) (code \ point) (code point) U n i c o d e Unicode Unicode 标准给定编码空间为 U+0000 - U+10FFFF。码点以 U + U+ U+ 开头,最少用 4 4 4 个十六进制数表示,若有前导 0 0 0 不可省略。例如: U + 00 F 7 U+00F7 U+00F7 表示除法符号 ÷ ÷ ÷

编码空间中有效码点个数为: 2 20 + ( 2 16 − 2 11 ) = 1112064 2^{20} + (2^{16} − 2^{11}) = 1112064 220+(216211)=1112064。其减掉的 2 11 2^{11} 211 主要原因在于 u t f 16 utf16 utf16 编码的编码方式限制,在范围 U+D800 - U+DFFF U n i c o d e Unicode Unicode 并未编码字符。

下表随机列了几个 U n i c o d e Unicode Unicode 码点和其表示的字符之间的对应关系:

码点Value
U+2118 P \huge\mathscr{P} P
U+A015
U+FE18

另外,按照码点范围区分了不同平面,以下为具体平面名称:

码点范围平面
U+0000-U+FFFF基本多文种平面
U+10000-U+1FFFF多文种补充平面
U+20000-U+2FFFF表意文字补充平面
U+30000-U+DFFFF表意文字第三平面
U+E0000-U+EFFFF特别用途补充平面
U+F0000-U+FFFFF保留作为私人使用区域A区
U+100000-U+10FFFF保留作为私人使用区域B区

基本多文种平面包含了绝大部分常用字符,例如: U + 0980 − U + 09 F F U+0980-U+09FF U+0980U+09FF 为孟加拉文, U + 25 A 0 − U + 25 F F U+25A0-U+25FF U+25A0U+25FF 为几何图形, U + 1800 − U + 18 A F U+1800-U+18AF U+1800U+18AF 为蒙古文,等等。具体见:Unicode符号表

utf32编码

u t f 32 utf32 utf32 编码方式非常简单直观:用 32 b i t 32bit 32bit 直接表示一个 U n i c o d e Unicode Unicode 码点,因此其也被称为定长编码。

1 1 1 U n i c o d e Unicode Unicode 标准规定的编码空间: U+0000 - U+10FFFF。最长需要 3 3 3 个字节表示, 4 4 4 字节完全够用。

2 2 2:以码点 U + 0041 U+0041 U+0041 字符 A A A 为例,其 u t f 32 utf32 utf32 编码结果为: 0 x 00000041 0x00000041 0x00000041。直观来讲, u t f 32 utf32 utf32 编码方式相当于把码点零扩展到 32 b i t 32bit 32bit。类似的, A S C I I ASCII ASCII 码也是一样的,零扩展到 7 b i t 7bit 7bit 表示。

缺点:
1 1 1 u t f 32 utf32 utf32 编码最大的缺点在于占用空间过大。假设一个文件内容只包含 A S C I I ASCII ASCII 字符集中的字符,那么用 u t f 8 utf8 utf8 来存储所需的空间是用 u t f 32 utf32 utf32 来存储的 1 / 4 1/4 1/4
2 2 2 u t f 32 utf32 utf32 不兼容 A S C I I ASCII ASCII 码。即:同样一个十六进制表示 0 x 41 0x41 0x41,在 A S C I I ASCII ASCII u t f 8 utf8 utf8 两种编码中表示内容一样且都为字符 A A A 的合法编码。

utf8编码

u t f 8 utf8 utf8 编码和 u t f 16 utf16 utf16 都为变长编码。 u t f 8 utf8 utf8 1 − 4 1-4 14 字节来表示一个特定字符。具体编码规则如下所示:

码点范围码点二进制表示编码规则字节数
U + 0000 − U + 007 F U+0000-U+007F U+0000U+007F 0 b x x x x x x x 0bxxxxxxx 0bxxxxxxx 0 b 0 x x x x x x x 0b0xxxxxxx 0b0xxxxxxx1字节
U + 0080 − U + 07 F F U+0080-U+07FF U+0080U+07FF 0 b x x x x x x x x x x x 0bxxx \ xxxx\ xxxx 0bxxx xxxx xxxx 0 b 110 x x x x x 10 x x x x x x 0b110xxxxx \ 10xxxxxx 0b110xxxxx 10xxxxxx2字节
U + 0800 − U + F F F F U+0800-U+FFFF U+0800U+FFFF 0 b x x x x x x x x x x x x x x x x 0bxxxx\ xxxx \ xxxx \ xxxx 0bxxxx xxxx xxxx xxxx 0 b 1110 x x x x 10 x x x x x x 10 x x x x x x 0b1110xxxx \ 10xxxxxx \ 10xxxxxx 0b1110xxxx 10xxxxxx 10xxxxxx3字节
U + 01 0000 − U + 10 F F F F U+01 \ 0000-U+10 \ FFFF U+01 0000U+10 FFFF 0 b x x x x x x x x x x x x x x x x x x x x x 0bx \ xxxx \ xxxx \ xxxx \ xxxx\ xxxx 0bx xxxx xxxx xxxx xxxx xxxx 0 b 11110 x x x 10 x x x x x x 10 x x x x x x 10 x x x x x x 0b11110xxx \ 10xxxxxx \ 10xxxxxx \ 10xxxxxx 0b11110xxx 10xxxxxx 10xxxxxx 10xxxxxx4字节

1 1 1:编码时只需根据码点范围按照码点二进制表示,高位补 0 0 0,填充编码规则中所需的空缺即可。
2 2 2:解码时只需要考虑首字节中最高位 0 b i t 0bit 0bit 左侧 1 b i t 1bit 1bit 的个数,即为当前字符所占用字节数。
例如:编码 U + 00 E 9 U+00E9 U+00E9 对于字符为 e ˊ é eˊ。根据范围知道其需要二字节编码, 0 0 0 扩展到 11 b i t 11bit 11bit 0 b 000 1110 1001 0b000 \ 1110 \ 1001 0b000 1110 1001。依次填充可知该字符 u t f 8 utf8 utf8 编码结果为 0 b 11000011 10101001 = 0 x c 3 a 9 0b11000011 \ 10101001=0xc3a9 0b11000011 10101001=0xc3a9

utf8编码函数示例

下面给出编码函数如下所示:

参数buf为待填入编码值的缓冲区,c为32位unicode码点
返回值为该字符所需编码长度

int encode_utf8(char *buf, uint32_t c) {// 一字节编码if (c <= 0x7F) {buf[0] = c;return 1;}// 二字节编码,首字节待填充5位,第二字节待填充6位if (c <= 0x7FF) {buf[0] = 0b11000000 | (c >> 6);buf[1] = 0b10000000 | (c & 0b00111111);return 2;}// 三字节编码,首字节待填充4位,第二字节待填充6位,第三字节待填充6位if (c <= 0xFFFF) {buf[0] = 0b11100000 | (c >> 12);buf[1] = 0b10000000 | ((c >> 6) & 0b00111111);buf[2] = 0b10000000 | (c & 0b00111111);return 3;}// 四字节编码,首字节待填充3位,第二字节待填充6位,第三字节待填充6位,第四字节待填充6位buf[0] = 0b11110000 | (c >> 18);buf[1] = 0b10000000 | ((c >> 12) & 0b00111111);buf[2] = 0b10000000 | ((c >> 6) & 0b00111111);buf[3] = 0b10000000 | (c & 0b00111111);return 4;
}

可通过如下主函数测试该编码函数的正确性:

int main(){char buf[4];int len=encode_utf8(buf,0x000000E9);system("chcp 65001");                // 终端使用utf8编码for(int i=0;i<len;i++)printf("%x",(unsigned char)buf[i]);std::cout<<std::endl;std::cout<<buf<<std::endl;return 0;
}

v s c o d e + m i n g w vscode+mingw vscode+mingw 的环境下有输出如下所示:

在这里插入图片描述

utf8解码函数示例

下面给出解码函数如下所示:

参数buf为给定utf8编码序列
返回值为该字符unicode码点

uint32_t decode_utf8(char *p) {// 单字节编码if ((unsigned char)*p < 128) {return *p;}int len;uint32_t c;if ((unsigned char)*p >= 0b11110000) {        // 四字节编码,起始11110xxx,3bit有效len = 4;c = *p & 0b111;} else if ((unsigned char)*p >= 0b11100000) { // 三字节编码,起始1110xxxx,4bit有效len = 3;c = *p & 0b1111;} else if ((unsigned char)*p >= 0b11000000) { // 二字节编码,起始110xxxxx,5bit有效len = 2;c = *p & 0b11111;} else {std::cout<<"invalid UTF-8 sequence"<<std::endl;}for (int i = 1; i < len; i++) {if ((unsigned char)p[i] >> 6 != 0b10)std::cout<<"invalid UTF-8 sequence"<<std::endl;c = (c << 6) | (p[i] & 0b111111);}return c;
}

可通过如下主函数测试该编码函数的正确性:

int main(){unsigned char buf[4]={0xc3,0xa9,0x00,0x00};uint32_t code=decode_utf8((char*)buf);system("chcp 65001");std::cout<<buf<<std::endl;std::cout<<std::hex<<code<<std::endl;return 0;
}

v s c o d e + m i n g w vscode+mingw vscode+mingw 的环境下有输出如下所示:

在这里插入图片描述

utf16编码

u t f 16 utf16 utf16 为变长编码,采用 2 2 2 字节或 4 4 4 字节编码。不兼容 A S C I I ASCII ASCII 码。

上文提到,码点范围从 U + 0000 U+0000 U+0000 U + F F F F U+FFFF U+FFFF 为基本多文种平面,包括绝大多数常用字符。 u t f 16 utf16 utf16 编码对常用的基本多文种平面直接使用 2 2 2 字节编码,超过这个范围的码点使用 4 4 4 字节编码。
具体编码规则如下所示:

码点范围码点二进制表示编码规则字节数
U + 0000 − U + F F F F U+0000-U+FFFF U+0000U+FFFF 0 b x x x x x x x x x x x x x x x x 0bxxxxxxxx \ xxxxxxxx 0bxxxxxxxx xxxxxxxx 0 b x x x x x x x x x x x x x x x x 0bxxxxxxxx \ xxxxxxxx 0bxxxxxxxx xxxxxxxx2字节
U + F F F F − U + 10 F F F F U+FFFF-U+10FFFF U+FFFFU+10FFFF c o d e p o i n t − 0 x 10000 = 0 b y y y y y y y y y y x x x x x x x x x x code \ point - 0x10000=0byyyy \ yyyy \ yyxx \ xxxx \ xxxx code point0x10000=0byyyy yyyy yyxx xxxx xxxx 0 x D 800 + 0 b y y y y y y y y y y 0xD800+0byyyy \ yyyy \ yy 0xD800+0byyyy yyyy yy
0 x D C 00 + 0 b x x x x x x x x x x 0xDC00+0bxx \ xxxx \ xxxx 0xDC00+0bxx xxxx xxxx
4字节

1 1 1:这里四字节编码中码点需要减去 0 x 10000 0x10000 0x10000 ,最大码点 0 x 10 F F F F − 0 x 10000 = 0 x F F F F F 0x10FFFF-0x10000=0xFFFFF 0x10FFFF0x10000=0xFFFFF
2 2 2:上文提及 u t f 16 utf16 utf16 编码特性使得 U n i c o d e Unicode Unicode 标准中有 2 11 2^{11} 211 个码点未编码实际字符,该未编码字符的码点范围为: U + D 800 U+D800 U+D800 U + D F F F U+DFFF U+DFFF。用来作为 u t f 16 utf16 utf16 四字节编码的范围。

utf16编码解码函数示例

下面给出编码函数如下所示:

参数buf为待填入编码值的缓冲区,缓冲区单元为2字节单元,c为32位unicode码点
返回值为该字符所需编码长度

int encode_utf16(uint16_t *buf, uint32_t c) {int len=0;if (c < 0x10000) {// 2字节编码buf[len++] = c;return 2;} else {// 4字节编码c -= 0x10000;buf[len++] = 0xd800 + ((c >> 10) & 0x3ff);buf[len++] = 0xdc00 + (c & 0x3ff);return 4;}
}

下面给出解码函数如下所示:

参数buf为填入编码值的缓冲区,缓冲区单元为2字节单元
返回值为该字符的unicode码点

uint32_t decode_utf16(uint16_t *buf) {uint32_t code;if ((*buf) >= 0xD800 && (*buf) <= 0xDBFF) {code = ((*buf)-0xD800)&0x3ff;buf++;if (!(*buf) >= 0xDC00 && (*buf) <= 0xDFFF){std::cerr<<"error utf16 code"<<std::endl;return 0;}code = (code<<10)|(((*buf)-0xDC00)&0x3ff);return code+0x10000;} else {return *buf;}
}

可通过如下主函数测试该编码解码函数的正确性:

int main(){uint16_t buf[2];int len=encode_utf16(buf,0x10ABC);for(int i=0;i<len/2;i++)printf("%x",buf[i]);printf("\n");uint32_t code=decode_utf16(buf);printf("0x%08x",code);printf("\n");return 0;
}

v s c o d e + m i n g w vscode+mingw vscode+mingw 输出如下图所示:

在这里插入图片描述

注:关于 u t f 32 utf32 utf32 编码到 U n i c o d e Unicode Unicode 码点的转换则不需要程式,直接通过无符号扩展到 32 b i t 32bit 32bit 即可,不再给出。

总结

完结撒花!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1421640.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

In Context Learning(ICL)个人记录

In Context Learning&#xff08;ICL&#xff09;简介 In Context Learning&#xff08;ICL&#xff09;的关键思想是从类比中学习。上图给出了一个描述语言模型如何使用 ICL 进行决策的例子。首先&#xff0c;ICL 需要一些示例来形成一个演示上下文。这些示例通常是用自然语言…

如何在群晖NAS中开启FTP并实现使用公网地址远程访问传输文件

文章目录 1. 群晖安装Cpolar2. 创建FTP公网地址3. 开启群晖FTP服务4. 群晖FTP远程连接5. 固定FTP公网地址6. 固定FTP地址连接 本文主要介绍如何在群晖NAS中开启FTP服务并结合cpolar内网穿透工具&#xff0c;实现使用固定公网地址远程访问群晖FTP服务实现文件上传下载。 Cpolar内…

Requests —— 请求头设置!

前戏 在我们进行自动化测试的时候&#xff0c;很多网站都会都请求头做个校验&#xff0c;比如验证 User-Agent&#xff0c;看是不是浏览器发送的请求&#xff0c;如果我们不加请求头&#xff0c;使用脚本访问&#xff0c;默认User-Agent是python&#xff0c;这样服务器如果进行…

2024年淘宝天猫618超级红包领取口令活动时间是从什么时候开始到几月几号结束?

2024年淘宝天猫618活动&#xff0c;将于2024年5月19日开始&#xff0c;今年618淘宝天猫取消了预售环节。同时&#xff0c;618淘宝天猫也提供了多项优惠活动&#xff1a;超级红包、跨店满减、官方立减、全程价保及草柴APP领优惠券拿购物返利等多重优惠活动。 2024年淘宝天猫618…

leetcode经典例题之环形队列

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 目录 1、题目展示2、问题分析3、完整代码展示4、结语 1、题目展示 在拿到题目时&#xff0c;通…

Python---NumPy万字总结【此篇文章内容难度较大,线性代数模块】(3)

NumPy的应用&#xff08;3&#xff09; 向量 向量&#xff08;vector&#xff09;也叫矢量&#xff0c;是一个同时具有大小和方向&#xff0c;且满足平行四边形法则的几何对象。与向量相对的概念叫标量或数量&#xff0c;标量只有大小&#xff0c;绝大多数情况下没有方向。我们…

找不到iutils.dll怎么解决,需要如何修复

iutils.dll 是一个系统级的动态链接库&#xff08;Dynamic Link Library&#xff09;文件&#xff0c;通常与Windows操作系统中的应用程序运行密切相关。动态链接库文件如同一个代码库&#xff0c;存储了多个程序可以共享的功能和指令。iutils.dll具体提供了哪些功能可能依据它…

模型 洋葱模型(组织文化方向)

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。层层深入&#xff0c;探索核心。 1 洋葱模型的应用 1.1 洋葱模型用于职业规划 有一个名叫李明的大学生&#xff0c;他最近感到迷茫和压力&#xff0c;因为他即将毕业并面临职业选择。李明决定寻求心…

Skywalking 8.x部署

一、下载版本 Skywalking 官网下载地址 版本地址 大家各自选取对应的版本即可 解压后&#xff1a; 二、修改配置 找到config目录下的application.yml 1. 修改存储方式为mysql 修改数据库jdbc连接信息 下一步懂得都懂,那肯定就需要mysql-connector-java-8.0.16写入mysql的…

【一触即发】快来围观C3安全大会酷炫九宫格!

C3安全大会2024 2024年5月18日 南京扬子江国际会议中心 C3安全大会2024 即将揭幕&#xff01; 图解C3 | 九宫格 数智变革&#xff0c;“AI”正以其颠覆性力量&#xff0c;重塑我们对未来的定义。亚信安全邀您共襄盛举&#xff0c;见证这场于5月18日盛大开幕的C3安全大会2024…

Linux(多线程)

//blockQueue.hpp #pragma once #include <iostream> #include <queue> #include <pthread.h> const int gcap 5; template <class T> class BlockQueue { public:BlockQueue(const int cap gcap):_cap(cap)//初始化阻塞队列的容量{pthread_mutex_in…

力扣HOT100 - 70. 爬楼梯

解题思路&#xff1a; 动态规划 注意 if 判断和 for 循环 class Solution {public int climbStairs(int n) {if (n < 2) return n;int[] dp new int[n 1];dp[1] 1;dp[2] 2;for (int i 3; i < n; i) {dp[i] dp[i - 1] dp[i - 2];}return dp[n];} }

美股开户,你需要知道这些!

想投资美股&#xff0c;却不知道开户需要多少钱&#xff1f; 别担心&#xff0c;这篇专栏将告诉你美股开户的资金要求以及相关注意事项。 1. 美股开户需要多少钱&#xff1f; 答案是&#xff1a;有的&#xff0c;但门槛并不高。不同平台对开户资金的要求有所不同&#xff0c;一…

visual studio2022 JNI极简开发流程

文章目录 1 创建java类2 生成JNI头文件3 使用visual studio2022创建DLL项目3.1 选择模板中&#xff08;Windows桌面向导&#xff09;3.2 为项目命名3.3 选择应用程序类型为动态链接库3.4 项目概览 4 导入需要的头文件4.1 导入需要的头文件4.2 修改头文件 5 编写C实现6 生成dll文…

外卖点餐小程序平台源码系统 自由切换 轻松管理 附带源码代码包以及系统搭建教程

系统概述 外卖点餐小程序平台源码系统是一款集点餐、支付、配送、评价等功能于一体的综合性平台。该系统采用先进的互联网技术&#xff0c;支持多种支付方式&#xff0c;包括微信支付、支付宝等&#xff0c;同时支持多平台使用&#xff0c;包括微信小程序、支付宝小程序等。商…

【C++】string类常用函数用法总结

目录 常用函数一览 默认成员函数 与容量有关的函数 part 1 part 2 part 3 与访问和遍历有关的函数 与修改有关的函数 npos 与string相关的其它常用函数 常用非成员函数 getline和cin的区别 常用函数一览 //默认成员函数 string();string(const char* s);string(si…

专题模块项目功能说明和运行方法-01

项目集介绍 SpringbootSeries父工程 此模块中只有一个pom.xml文件&#xff0c;是后面所有模块的父模块&#xff0c;主要功能有两个&#xff1a;子模块管理和依赖管理。 类别必选可选基础框架jdk 17 spring-boot-starter 3.2.4spring-boot-starter-web 3.2.4spring-cloud 2023…

Find My腰包|苹果Find My技术与腰包结合,智能防丢,全球定位

腰包具有显瘦和显高的双重功效&#xff0c;它不仅能提高腰线、拉长腿部线条&#xff0c;还能遮住腹部多余的赘肉&#xff0c;从而在视觉上达到变高的效果&#xff0c;使整体看起来更加显瘦。除了时尚功能&#xff0c;腰包在运动中也有其独特的用途。例如&#xff0c;在跑步时&a…

基于SPWM控制策略的二极管钳位型的五电平逆变器simulink仿真

本人搭建了二极管钳位型五电平逆变器simulink仿真模型&#xff0c;SPWM采用层叠&#xff0c;输出线电压9电平&#xff0c;相电 压5电平&#xff0c;滤波后对称三相电压、电流&#xff0c;THD<5%&#xff0c;效果十分优越&#xff0c;适合新手学习使用。 模型获取链接&…

杨校老师项目之基于大数据技术栈hadoop商业web应用的日志分析系统

获取全套资料&#xff1a; 有偿获取&#xff1a;mryang511688 摘要&#xff1a; 互联网世界的先驱者们一致认为大数据将是未来互联网产业&#xff0c;甚至是整个人类各个产业的基础资源&#xff0c;那么到底什么是大数据&#xff0c;大数据给我们的世界是如何带来变化的呢&am…