恼人的“龙天“(䶮)--谈谈从GBK转到GB18030的特殊情况

2024-01-12 19:36

本文主要是介绍恼人的“龙天“(䶮)--谈谈从GBK转到GB18030的特殊情况,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

最近在做一个去O迁移适配,刚好也有友商在一起做,两边测试方式不一样。友商先遇到了一个问题,就是在ORACLE中某个的2字节GBK字符到迁移到友商的库中变成了4字节,刚好那个字段在这个字是2字节的时候,已经存满了,转换成4字节后就会超长,死活都导不进去,经分析,是因为友商建库时选择了GB18030字符集,可是为什么2字节的GBK字符到了GB18030会变成4字节?而我在MogDB中建GBK的库,这个字能正常导入,不会超长。
这个字有何神奇之处?
在经过一些调查及测试验证后,特整理此文。

分析过程

这个字的外形是 ,上面是“龙”,下面是“天”。其实正常的输入法是可以输入这个外形的字的,但是,实际上你用输入法输入的这个字,并不是我上面提到的这个字,它们只是外形完全一样的“两个字”,这里我说“两个字”是对于unicode编码而言,或者换种说法,这个外形的字,在GB(GBK/GB18030)字符集的演进历史中,曾经占据了两个unicode编码,在windows中文区域里,使用ANSI时 ,这两个unicode编码的字符都可以正常显示字形。而在流行的UTF8编码的网页上,其中一个字可能是无法正常显示的,而这个字就是数据库迁移中存在问题的字,而这个字的起源,要追述到GBK编码定义


(https://www.zhihu.com/question/403694151)
如上图 右下角的位置,GBK+FE9F 这个编码,对应的unicode编码为U+E863,然后我们去查下unicode官网,找找这个编码,

在这里插入图片描述

在unicode官网里,这个编码并没有字形对应,而且该位置属于PUA(私人编码区)。

我们再来看GB18030-2022中U+E863是什么
在这里插入图片描述

U+E863对应的GB18030编码为 GB18030+8336CF39 ,此处也没有字形。也就是说,GBK编码的FE9F这个字,既不被UNICODE承认,也不在最新的国家强制标准GB18030-2022里。

可是,不是说GB18030比GBK能支持更多的生僻字么?其实,这个字并不是没有了,而是GB18030把它"直接兼容"了。

我们直接用GBK编码的FE9F在GB18030标准里找
在这里插入图片描述

可以看到这里的确有对应的字形,而且就是“龙天”,这个字对应的UNICODE编码为U+4DAE,于是我们再去UNICODE官网找找
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

果然在这里也能找到。

我们以UNICODE编码来整理一下这两个字的各种编码(由于这个字在UTF8中没有字形对应,所以可能部分网页上会显示方框,如果复制出来放到中国区域的windows的记事本里,就可以正常显示对应的字,因为当成GBK显示了)

UNICODE4DAEE863
UTF8E4B6AEEEA1A3
GB18030FE9F8336CF39
GBKFE9F

然后我测试了,在较新版本的ORACLE中,使用UTL_I18N里的raw_to_char/string_to_raw函数,也可以得到上述相同的结果

SQL> WITH T AS2  (SELECT UTL_I18N.RAW_TO_CHAR('4DAE','AL16UTF16') U4DAE ,3  UTL_I18N.RAW_TO_CHAR('E863','AL16UTF16') UE863 FROM DUAL)4  SELECT 'AL32UTF8' encoding, UTL_I18N.STRING_TO_RAW(U4DAE,'AL32UTF8') "4DAE",5  UTL_I18N.STRING_TO_RAW(UE863,'AL32UTF8') "E863" FROM T6  UNION ALL7  SELECT 'ZHS32GB18030',UTL_I18N.STRING_TO_RAW(U4DAE,'ZHS32GB18030'),8  UTL_I18N.STRING_TO_RAW(UE863,'ZHS32GB18030') FROM T9  UNION ALL10  SELECT 'ZHS16GBK',UTL_I18N.STRING_TO_RAW(U4DAE,'ZHS16GBK'),11  UTL_I18N.STRING_TO_RAW(UE863,'ZHS16GBK') FROM T;ENCODING     4DAE    E863
------------ ------- ---------
AL32UTF8     E4B6AE  EEA1A3
ZHS32GB18030 FE9F    8336CF39
ZHS16GBK     A3BF    FE9FSQL>

这里注意ORACLE中的 U+4DAE 在ZHS16GBK其实并不是 “A3BF”,而是因为并没有对应的字符,ORACLE把它转换成了全角问号(转成什么符号与当前环境的区域语言有关)。

引发的问题

所以,这里出现一个很尴尬的情况:
在去O过程中,原本在Oracle中使用的是GBK字符集,存入了GBK字符集支持的"FE9F"这个字符,如果迁移的目标库也是使用GBK字符集,那当然皆大欢喜。可是GBK目前已被国家标准废弃,必须要使用GB18030,而编码转换软件如果按照UNICODE标准进行转换,那么这个字将被转换成GB18030的"8336CF39" ,且不说数据可能会变长导致无法存入数据库,更大的问题是,GB18030中的"8336CF39"并没有对应的字形,会导致很多软件的UI无法显示这个字!

于是对于GBK和GB18030的转换,就不应该使用UNICODE的码点对应关系来进行转换了,这对于现有的绝大多数会涉及到文本转码的软件带来灾难。现有很多开发语言的内部都是默认使用的UTF8(比如JAVA、GO),各种字符的转入转出几乎都是通过UNICODE来进行中转,遇到这种转换的场景,很有可能会出现问题。相关报道有很多,这里随便列两篇:

1.# 谈困在系统里的生僻字,如何消除数字化“盲区”?

2.# 一个名字叫“䶮”的人的苦恼:开不了银行账户,用不了微信、支付宝

处理建议

  1. 对于软件开发商,转码软件或者转码模块应该单独编写GBK到GB18030的转码规则。比如本文的例子,GBK的 “FE9F” ,就应该映射到 GB18030的 “FE9F” ,而非通过UNICODE编码进行中转得到的 “8336CF39”;或者更新GBK的映射,使其unicode码和GB18030的映射关系一致(windows就是这么处理的 : windows-936-2000)
  2. 对于对被强制执行标准的软件用户,应提前采取措施应对GBK编码转到GB18030所带来的影响(原本用UTF8转到GB18030的没有此类问题),不是所有的软件开发商都会细致地去考虑编码转换问题,GB18030强制标准只要求能支持输入输出标准里的字符,并不要求支持和其他字符集进行转换。
  3. 对于所有的新软件开发,不应再使用GBK字符集,推荐使用UTF8(或者GB18030)
  • 本文作者: DarkAthena
  • 本文链接: https://www.darkathena.top/archives/longtian-yan-encoding-gbk-gb18030
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!

这篇关于恼人的“龙天“(䶮)--谈谈从GBK转到GB18030的特殊情况的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/598936

相关文章

BUUCTF(34)特殊的 BASE64

使用pycharm时,如果想把代码撤销到之前的状态可以用 Ctrl+z 如果不小心撤销多了,可以用 Ctrl+Shift+Z 还原, 别傻傻的重新敲了 BUUCTF在线评测 (buuoj.cn) 查看字符串,想到base64的变表 这里用的c++的标准程序库中的string,头文件是#include<string> 这是base64的加密函数 std::string

如何保证android程序进程不到万不得已的情况下,不会被结束

最近,做一个调用系统自带相机的那么一个功能,遇到的坑,在此记录一下。 设备:红米note4 问题起因 因为自定义的相机,很难满足客户的所有需要,比如:自拍杆的支持,优化方面等等。这些方面自定义的相机都不比系统自带的好,因为有些系统都是商家定制的,难免会出现一个奇葩的问题。比如:你在这款手机上运行,无任何问题,然而你换一款手机后,问题就出现了。 比如:小米的红米系列,你启用系统自带拍照功能后

特殊JSON解析

一般的与后台交互;都会涉及到接口数据的获取;而这里的数据一般情况就是JSON 了;JSON 解析起来方便;而且数据量也较小一些;所以JSON在接口数据返回中是个很不错的选择。 下面简单说下JSON解析过程中的一些案例: 这里我用到了三方的架包:fastjson-1.1.39.jar 架包 可以在我的博客中找到下载;或者网上找下 很多的; 这里主要就是映射  关系了;这就要求:实体类的名称和

Windows11电脑上自带的画图软件修改照片大小(不裁剪尺寸的情况下)

针对一张图片,有时候上传的图片有大小限制,那么在这种情况下如何修改其大小呢,在不裁剪尺寸的情况下 步骤如下: 1.选定一张图片,右击->打开方式->画图,如下: 第二步:打开图片后,我们可以看到图片的大小为82.1kb,点击上面工具栏的“重设大小和倾斜”进行调整,如下: 第三步:修改水平和垂直的数字,此处我修改为分别都修改为50,然后保存,可以看到大小变成63.5kb,如下:

postgres数据库中如何看查询是否走索引,以及在什么情况下走索引

在 PostgreSQL 中,可以通过 EXPLAIN 或 EXPLAIN ANALYZE 查看查询计划,以判断查询是否使用了索引。除此之外,了解索引的使用条件对于优化查询性能也很重要。 1. 如何查看查询是否使用索引 使用 EXPLAIN 查看查询计划 EXPLAIN 显示 PostgreSQL 如何执行查询,包括是否使用索引。 EXPLAIN SELECT * FROM users WH

linux 查看内存使用情况

Linux查看CPU和内存使用情况:http://www.cnblogs.com/xd502djj/archive/2011/03/01/1968041.html 在做Linux系统优化的时候,物理内存是其中最重要的一方面。自然的,Linux也提供了非常多的方法来监控宝贵的内存资源的使用情况。下面的清单详细的列出了Linux系统下通过视图工具或命令行来查看内存使用情况的各种方法。 1. /pr

ubuntu内存资源使用情况监视

此处分享一个可以查看ubuntu系统中资源使用情况的指令,只需要在终端中输入一下这条指令即可: gnome-system-monitor

广东省特殊食品生产试题分享

1.食品污染是指在各种条件下,导致有毒有害物质进入到食物中,造成以下哪项发生转变的过程。(D) A.食品的安全性 B.食品的养分性 C.食品的感官性状 D.以上都是 2.食品污染物是指(D) A.生物性污染物 B.化学性污染物 C.物理性污染物 D.以上都是 3.关于菌落总数的表达,错误的选项是(A) A.反映食品对人体安康的危害程度 B.是食品清洁状态的标志 C.推测食品的耐保藏性 D.指1g检

在不损坏数据的情况下给WIN7重新划分分区

小易接到个求助电话:我的机器上已经装好了系统,但是只有一个分区。我不想重装系统重新分区,能不能再分出一个分区?   这个故障可能是困惑很多网友的一个故障。一般,有一些第三方的软件可以实现这些功能。但是,现在在 Windows Vista/Windows 7 里允许你对现有分区大小进行一定范围的调整。   来看一下操作办法:   准备工作   这个操作必须要求你的文件系统是 N

批量文件编码转换用python实现的utf8转gb2312,vscode设置特殊文件的默认打开编码

批量文件编码转换用python实现的utf8转gb2312, 任意编码之间的相互转换都是可以的.改一下下面的参数即可 convert.py文件内容如下 import osimport globimport chardet#检测文件编码类型def detect_file_encoding(file_path):with open(file_path, 'rb') as f:data = f