你能看到这个汉字么“ ” ?关于Unicode的私人使用区(PUA) 和浏览器端显示处理
如果你现在使用的是chrome查看那么你是看不到我标题中的汉字的,显示为一个小方框,但是你使用edge查看的话,这个字就能正常的显示出来,不信你试试!
本故事源于我在做数据过程中遇到Unicode编码中的私人使用区PUA编码的汉字,然后导入到产品端后他们说有些汉字是乱码无法显示,然后针对这个问题进行了排查。
首先在我标题中的汉字是如下汉字:

Unicode
其实我之前的文章都提到过很多编码的问题,平时对编码问题也比较了解,所以拿到这个问题首先我这边数据处理用的utf-8,关于utf-8和unicode的关系就不赘述了。因为我这边能正常在sqlserver里面看到这个字,所以可以确定它不是一个乱码,至少是一个符合规范的unicode编码。然后我用工具查看了这个字的编码为 U+E188。查看文字的unioncode编码也可以使用在线工具https://symbl.cc/cn/
关于Unicode的分区:
在Unicode中,码位的总范围为\x0到\x10FFFF,共1,114,112个码位。2048个用于编码代理(UTF-16),66个非字符码位(例如BOM),137,468个预留给私人使用,最终剩余974,530用于普通字符分配。
码位的最大值为\x10FFFF,对应二进制有21位,将216个值分为一组,Unicode总共可以分为17份,每一份称之为平面(Plane),每一个平面有65,536(216)个码位。
为什么Unicode的最大值为\x10FFFF?因为对于UTF16编码,双字节最多可编码220个字符,单字节可编码216个字符,加起来共17个平面的字符数。
| 平面编号 | 码位范围 | 名称简写 | 名称描述 |
|---|---|---|---|
| Plane 0 | 0000–FFFF | BMP | 基础多语言平面(Basic Multilingual Plane) |
| Plane 2 | 10000–1FFFF | SMP | 补充多语言平面(Supplementary Multilingual Plane) |
| Plane 2 | 20000–2FFFF | SIP | 补充表意语言平面(Supplementary Ideographic Plane) |
| Plane 3 | 30000–3FFFF | TIP | 第三表意语言平面(Tertiary Ideographic Plane) |
| Planes 4–13 | 40000–DFFFF | - (未分配) | - (未分配) |
| Plane 14 | E0000–EFFFF | SSP | 补充特殊用途平面(Supplementary Special-purpose Plane) |
| Planes 15–16 | F0000–10FFFF | SPUA-A/B | 补充私有使用区平面(Supplementary Private Use Area planes) |
通过这个平面表我们可以看到该字的编码在BMP中,Unicode中,私人使用区(PUA)是一系列代码点,根据定义,Unicode 联盟不会为其分配字符,定义了二个私人使用区域:一个位于基本多语言平面( U+E000-U+F8FF),一个位于并几乎覆盖平面 15 和 16(U+F0000-U+FFFFD ,U+ 100000-U+10FFFD )即SPUA。这些区域中的代码点不能被视为 Unicode 本身的标准化字符。
字符集和字体
Windows 允许 在双字节字符集中 (DBCS) 和 Unicode 中对非标准字符进行本地定义。 对于 DBCS,这些非标准字符称为最终用户定义字符, (EUDC) 。 Unicode 通过其专用区域 (PUA) 提供类似的功能。 应用程序通过使用关联的 DBCS 或 Unicode 字符值来标识指定的字符。
可以分配的 DBCS 字符值取决于指定的字符集。 每个东亚 Windows 代码页 至少有一个保留值范围用作 EUDC。 范围由 EUDCCodeRange 注册表项定义。 用于此目的的 Unicode 值始终来自 Unicode PUA,值 U+E000 到 U+F8FF,U+F0000 到 U+FFFFD,U+100000 到 U+10FFFD。
若要创建 EUDC 或 PUA 字符,用户选择指定范围内的字符值,并将 字形 添加到与该字符值相对应的条目中的字体中。 用户使用 EUDC 编辑器或使用从字体供应商处购买的字体包创建字形。 任何 DBCS 字体都可以包含 EUDC,任何 Unicode 字体都可以包含 PUA 字符。 如果字体仅包含 EUDC/PUA,则称为“独立”EUDC/PUA 字体。 如果字体包含标准字符和 EUDC,则为“集成”EUDC/PUA 字体。
系统默认的 EUDC/PUA 字体是操作系统自动与所有 DBCS 和 Unicode 字体关联的字体,但具有显式关联的 EUDC/PUA 字体的字体除外。 应用程序通过在 EUDC 注册表项下设置 SystemDefaultEUDCFont 名称的值来设置系统默认 的 EUDC /PUA 字体。 同样,应用程序可以通过在 EUDC 键下指定字体名称和关联的字体文件,将单独的 EUDC/PUA 字体与相应的字体相关联。 操作系统始终首先尝试查找当前所选字体中的 EUDC/PUA。 如果未找到该字体,则操作系统将在关联的 EUDC/PUA 字体中查找字符(如果已为当前所选字体定义了一个字体)。 如果仍然找不到字符,操作系统将在系统默认的 EUDC/PUA 字体中查找它。
TrueType 字体可以安装为 .ttf 文件或 .tte 文件。 由于操作系统隐藏 .tte 文件,因此应用程序无法使用 GDI API 函数枚举或以其他方式检查已安装的字体。 在许多操作系统上,系统默认的 EUDC/PUA 字体和单独的 EUDC/PUA 字体作为 .tte 文件安装。 EUDC 编辑器和控制面板等应用程序必须使用注册表项来添加、修改和删除此类字体
上面描述摘自微软文档https://learn.microsoft.com/zh-cn/windows/win32/intl/character-sets-and-fonts
EUDC 注册表项包含一个或多个子项,这些子项包含的值定义与给定代码页 的最终用户定义字符关联的字体 (EUDC) 。 它具有以下注册表位置:
HKEY_CURRENT_USER\EUDC
EUDCCodeRange 注册表项 (EUDC) 代码范围 (字符集) 定义最终用户定义字符。 它仅由创建 EUDC 的工具使用,对欧盟发展委员会用户没有直接关系。

显示
所以为啥微软系的应用能够显示这个字呢,上面字符集和字体描述可以看到自己可以定义EUDC,在微软字符映射表中有一类叫做“专用字符”,而这个专用字符就是我们自己可以定义的PUA区域。
我们找到系统的字符映射表:

可以看到这个字刚好对应U+E188。
我们找到注册表,并查看上面表格中codePage中对应的936为中文简体,看到字体文件位置。

找到对应的字体文件,并引入到html中,我们就能在任何浏览器看到这个字了。

简单的写一个html:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
@font-face {
font-family: "SGPYEUDC";
src: url("SGPYEUDC_1.TTE") format("truetype");
}
</style>
</head>
<body style="font-family:Microsoft YaHei,SGPYEUDC">
<p></p>
</body>
</html>

你能看到这个汉字么“ ” ?关于Unicode的私人使用区(PUA) 和浏览器端显示处理的更多相关文章
- json_encode如何防止汉字转义成unicode
众所周知,json_encode通常会把json中的汉字转义成unicode,但是这并不一定是我们想要的.有时候,我们需要获得汉字形式的json字符串,比如需要获得gbk编码的json字符串(只要把汉 ...
- 简体和繁体加起来有六七万个汉字,所以Unicode只能排除一些几乎不用的汉字,Unicode编码的熟悉与研究过程(内附全部汉字编码列表)
我有一个问题是:是不是会有个别汉字无法在Unicode下表示,这种情况下就不能完全显示了? 各种编码查询表:http://bm.kdd.cc/ ---------------------------- ...
- FreeMarker的基础语法
FreeMarker语言 FreeMarker语言概述 FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写. FreeMarker被设计用来生成HTML Web ...
- FreeMarker的基础语法使用 && 心得和技巧
FreeMarker语言 FreeMarker语言概述 FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写. FreeMarker被设计用来生成HTML Web ...
- freemarker模版引擎技术总结
FreeMarker语言概述 FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写. FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式 ...
- .Net(c#)汉字和Unicode编码互相转换
{"Tilte": "\u535a\u5ba2\u56ed", "Href": "http://www.cnblogs.com&q ...
- 各种编码中汉字所占字节数;中文字符集编码Unicode ,gb2312 , cp936 ,GBK,GB18030
vim settings set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936,latin1set termencoding=utf-8se ...
- JS之汉字与Unicode码的相互转化
有时候,我们在给后端传递变量的的值中有汉字,可能由于编码的原因,传递到后端后变为乱码了.所以有时候为了省事或者其它特殊要求的时候,会把传递的汉字转换成Unicode编码后再进行传递. 当然汉字转换成u ...
- python3进行汉字和unicode码的转换
输出某个unicode码对应的汉字和某个汉字对应的unicode编码. # -*- coding=UTF-8 -*- str1 = "\u6000"#某个汉字的unicode码 s ...
- c# 实现获取汉字十六进制Unicode编码字符串
1. 汉字转十六进制UNICODE编码字符串 /// <summary> /// //// /// </summary> /// & ...
随机推荐
- uni-app 打包发行
1.云端 发行-原生App-云打包 2.离线 运行-原生App本地打包-生成本地打包资源,如果提示安装依赖包,安装即可 注意:项目的AppID不能为空,请在该项目下的manifest.json中重新获 ...
- Vue 全局避免按钮重复点击
这里用到的 Vue.directive 自定义指令 自定义指令是对普通DOM元素进行的底层操作,它是一种有效的的补充和扩展,不仅可以用于定义任何的dom操作,并且是可以复用的 在 main.js 中写 ...
- [ARC114D] Moving Pieces on Line 解题报告
AT题面 简要题意 有一个红色的数轴,相邻两个整点之间连有一条边,所有边初始为红色.数轴上有 \(n\) 个棋子,将一个棋子从 \(a\) 位置移到 \(b\) 位置,可以将 \((a,b)\) 之间 ...
- 【.NET 深呼吸】全代码编写WPF程序
学习 Code 总有这样一个过程:入门时候比较依赖设计器.标记语言等辅助工具:等到玩熟练了就会发现纯代码写 UI 其实更高效.而且,纯代码编写也是最灵活的.Windows Forms 项目是肯定可以全 ...
- Git 多账号配置
本地登录多账号并连接对应的远程仓库,主要就是 密钥配对,我这里刚开始配了密钥也将密钥复制到ssh但是还是连接不到第二个远程仓库,后来发现是需要 密钥代理 1.在当前项目下更改git账号信息: git ...
- 【Azure 媒体服务】Azure Media Player 在Edge浏览器中不能播放视频问题的分析与解决
问题描述 使用Azure Media Service 制作视频点播服务,在客户端使用 Azure Media Player 播放器在 Edge 浏览器中播放视频时候遇见无法播放的问题: 错误信息: T ...
- 多线程知识:三个线程如何交替打印ABC循环100次
本文博主给大家讲解一道网上非常经典的多线程面试题目.关于三个线程如何交替打印ABC循环100次的问题. 下文实现代码都基于Java代码在单个JVM内实现. 问题描述 给定三个线程,分别命名为A.B.C ...
- Semantic Kernel(语义内核)秋季路线图
Semantic Kernel 是一个开源的 SDK,它允许开发人员将大型语言模型(LLM)与传统的编程语言进行混合使用. 微软Semantic Kernel团队 在博客上正式公布了Semantic ...
- python:导入库、模块失败
一般发生在程序开始部分: from pymodbus.client.sync import ModbusSerialClient from pymodbus.payload import Binary ...
- UG NX实现叉车运输货物功能遇见的问题
在前一段时间编写模拟叉车运输功能时遇到,货物无法跟随的问题(如下动图) 后面发现是速度太快的原因导致货物没有跟着动,类似于抽桌布的感觉 解决办法有两种:第一种解决办法很简单就是把速度降低到不超过 2 ...