首页 > 其他分享 >UTF-8和GBK等中文字符编码格式介绍及相互转换

UTF-8和GBK等中文字符编码格式介绍及相互转换

时间:2023-08-15 10:15:09浏览次数:30  
标签:编码 UTF 字节 GB2312 GBK Unicode

我们有很多时候需要使用中文编码格式,比如gbk、gb2312等,但是因为主要针对中文编码设置,因此并不完全通用,这样一来就有了在各编码间相互转换的需求,比如和UTF8的转换。可是在我使用的过程中,却发现编码转换并没有想象中的简单,或者说可能会出错,即使你使用的系统API。我在使用中,产生一些疑惑,搜索资料也没有完全解决我的问题,因此整理了这篇文章。文章末尾列出了我参考的一些资料或者代码实现等,在此谢过。

      本文先各个中文编码进行介绍,只做简单介绍,不涉及详细原理(本文结尾附有链接可参阅),然后实例验证编码转换之间的问题。

各个编码格式介绍

  • GB2312

      GB2312是中华人民共和国国家汉字信息交换用编码,全称《信息交换用汉字编码字符集——*本集》,由国家标准总局发布,1981年5月1日实施,通行于大陆。新加坡等地也使用此编码。GB2312收录简化汉字及符号、字母、日文假名等共7445个图形字符,其中汉字占6763个。GB2312 规定“对任意一个图形字符都采用两个字节表示,每个字节均采用七位编码表示”,习惯上称第一个字节为“高字节”,第二个字节为“低字节”。

      GB2312的编码范围为2121H-777EH,与ASCII有重叠,通行方法是将GB码两个字节的最高位置1以示区别。

  • GBK

      GB2312 仅收汉字 6763 个,这大大少于现有汉字,随着时间推移及汉字文化的不断延伸推广,有些原来很少用的字,现在变成了常用字,例如:***的“*”字,未收入 GB2312-80,现在报业出刊只得使用(金+容)、(金容)、(左金右容)等来表示,形式不一而同,这使得表示、存储、输入、处理都非常不方便,而且这种表示没有统一标准。为了解决这些问题,以及配合UNICODE的实施,全国信息技术化技术委员会于1995年12月1日《汉字内码扩展规范》。GBK向下与GB2312 完全兼容,向上支持ISO 10646 国际标准,在前者向后者过渡过程中起到的承上启下的作用。GBK亦采用双字节表示,即不论中、英文字符均使用双字节来表示,为了区分中文,将其最高位都设定成1,总体编码范围为8140-FEFE之间,首字节在81-FE 之间,尾字节在40-FE 之间,剔除 XX7F 一条线。
GBK 共收入21886个汉字和图形符号,包括:
    * GB2312中的全部汉字、非汉字符号;
    * BIG5中的全部汉字;
    * 与ISO 10646相应的国家标准GB13000中的其它 CJK 汉字,以上合计20902个汉字;
    * 其它汉字、部首、符号,共计984个;

  • GB18030

      GB18030 是最新的汉字编码字符集的国家标准,向下兼容 GBK 和 GB2312 标准。GB18030 编码是一二四字节变长编码。一字节部分从 0x0~0x7F 与 ASCII 编码兼容。二字节部分,首字节从 0x81~0xFE,尾字节从 0x40~0x7E以及 0x80~0xFE,与GBK标准*本兼容。四字节部分,第一字节从 0x81~0xFE,第二字节从 0x30~0x39,第三和第四字节的范围和前两个字节分别相同。四字节部分覆盖了从 0x0080 开始, 除去二字节部分已经覆盖的所有 Unicode 3.1码位。也就是说,GB18030编码在码位空间上做到了与Unicode标准一一对应,这一点与UTF-8编码类似。

  • Unicode

      Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符。Unicode只是一个符号集, 它只规定了符号的二进制代码, 却没有规定这个二进制代码应该如何存储。比如UTF-8、UTF-16、UTF-32都是Unicode编码的实现方式,不过UTF-8是使用最多的实现。

  • UTF-8

      UTF-8:Unicode Transformation Format-8bit,允许含BOM,但通常不含BOM。是用以解决国际上字符的一种多字节编码,是在互联网上使用最广的一种unicode的实现方式。UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度,因此可以节省存储空间。它对英文使用8位(即一个字节),中文使用24为(三个字节)来编码。UTF-8包含全世界所有国家需要用到的字符,是国际编码,通用性强。UTF-8编码的文字可以在各国支持UTF8字符集的浏览器上显示。如果是UTF8编码,则在外国人的英文IE上也能显示中文,他们无需下载IE的中文语言支持包。

     UTF-8的编码规则很简单,只有二条:

            1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的;
            2)对于n字节的符号,第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的二进制位,表示为这个符号的unicode码;

      另外像ASCII只用于英文字符编码,BIG5编码是通行于台湾、香港地区的一个繁体字编码方案,虽然存在一些瑕疵,但广泛应用于电脑行业,尤其是互联网中,从而成为一种事实上的行业标准。

  • 总结
  1. ASCII用于表示英文字符,是用7位表示的,能表示128个字符;其扩展使用8位表示,表示256个字符;
  2. GB2312简体中文的编码格式, 只支持6763个常用汉字;
  3. GBK是GB2312*础上扩容后兼容GB2312的标准,包含全部中文字符,支持简体中文及繁体中文;
  4. GBK通用性比UTF8差,不过UTF8占用的数据库比GBK大;
  5. GB2312、GBK到GB18030都属于双字节字符集 (DBCS);
  6. 从ASCII、GB2312、GBK到GB18030,这些编码方法是向下兼容的,即同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符。在这些编码中,英文和中文可以统一地处理。区分中文编码的方法是高字节的最高位不为0;

GBK和UTF-8的相互转换

      好吧,这才是正题。

      从上面看到,一般来说UTF-8可应用于大多数场景,尤其是互联网上,而中文编码主要使用GBK编码,因此这就有了GBK、GB2312和UTF-8的相互转换需求。但要注意,GBK、GB2312等与UTF8之间都必须通过Unicode编码才能相互转换,也即:
    GBK、GB2312 ---> Unicode ---> UTF-8
    UTF8 ---> Unicode ---> GBK、GB2312

     比如拿汉字的“字”来举例,

 “字“的表示 二进制表示 16进制 10进制 字符串表示
GBK 11010111 11010110  D7 D6 55254
Unicode 01011011 01010111 5B 57 23383  
Utf-8 11100101 10101101 10010111 E5 AD 97 15052183

      同样,对于词语“中国.北京”,转换成UTF-8表示为:涓浗.鍖椾含。

      你要问我怎么转换的?原理什么的就不介绍了,在Windo平台下,通过一些Win API可以将GBK和Utf-8经过Unicode层进行相互转换。Linux下也是这样。另外由于各个编码规则都是确定的,因此各字符也就有了一种对应关系,这就使查表法也成为实现编码转换的一种方式。

GBK和UTF-8编码的检测

     上面简单介绍了各种编码以及他们的相互转换,但如果给定一个字符串,能够检测出其编码是什么吗? 比如对于“中国.北京”,检测出其为GBK或GB2312,而对于

”涓浗.鍖椾含“检测出其为UTF-8。那么对于一个给定的检测算法,是否保证肯定能检测到该字符串的真正编码方式吗?或者对于一个网页内容来说,很可能既存在GBK编码内容,也有UTF-8内容,那网页应该怎么显示(好像是检测编码,哪种编码出现的频率多,就使用哪种编码显示,臆测,不懂)?

     再举一个例子: “谢谢”,其UTF-8表示是“璋㈣阿”。从我的实现中,不论对于GBK编码的“谢谢”,还是UTF-8的“璋㈣阿”,都检测出是UTF-8编码。而我也不是第一个遇到这种情况的人,比如孟岩他老人家也遇到过检测失败的问题,不过他是在Ruby语言下发现的问题,而我是在C/C++实现中出现的检测失败。

     好吧,说到这里我也不知道说的是什么了,总之就是,

  • 各编码规则从应用角度来看,还挺复杂;
  • 编码转换和编码检测有时也不靠谱;

标签:编码,UTF,字节,GB2312,GBK,Unicode
From: https://www.cnblogs.com/zhenren001/p/17630564.html

相关文章

  • 数据结构(哈夫曼树):判定编码方案是否为前缀编码
    前缀编码定义:(字符集中)任一编码都不是其它字符的编码的前缀(字符集中)任一编码都不是其它字符的编码的前缀(字符集中)任一编码都不是其它字符的编码的前缀重要的话说三遍!例:(1)找出下面不是前缀编码的选项A{1,01,000,001}B{1,01,011,010}C{0,10,110,11}D{0,1,00,11}第一步:看A中的第一个数1,看看其他......
  • 问题解答:关于 SAP UI5 控制器(Controller) JavaScript 编码里单引号和双引号的用法澄
    笔者这篇教程文末,有朋友提问:SAPUI5应用开发教程之十-什么是SAPUI5应用的描述符文件manifest.json问题1:在index.html文件中body标签添加了代码:<divdata-sap-ui-componentdata-name="sap.ui5.walkthrough"data-id="container"data-settings='{"id":"wa......
  • 数据序列化工具Protobuf编码&避坑指南
    我们现在所有的协议、配置、数据库的表达都是以protobuf来进行承载的,所以我想深入总结一下protobuf这个协议,以免踩坑。先简单介绍一下ProtocolBuffers(protobuf),它是Google开发的一种数据序列化协议(与XML、JSON类似)。它具有很多优点,但也有一些需要注意的缺点:优点:效......
  • 跨平台xamarin.Android 开发之 :适配各架构(X86_64 、 X86、arm64-v8a、 armeabi-v7a )
    此代码的编写花费了脑细胞:在每次编码开启编码器到只需要一次编码器的开启优化前提:编译好FFMpeg的各平台的动态库基本上Android X86_64、X86、arm64-v8a、armeabi-v7a采用FFmpeg编码的方式基本一直。差异是内存分配和取指有所不同,如果分配不对,直接闪退。先看看通用的编码......
  • ASPICE流程编码和单元测试
    ASPICE流程编码和单元测试是指根据详细设计,编写符合ASPICE标准的代码,并对每个模块进行单元测试。这一过程包括以下步骤:编写代码:根据详细设计,编写符合ASPICE标准的代码,确保代码质量和可维护性。代码审查:对编写好的代码进行审查,发现并纠正潜在问题,确保代码质量和可靠性。单元测试计划......
  • java使用hutool把服务器图片链接转为base64编码
    需求是把服务器的图片链接或者网上的图片链接地址转为base64位编码方便前端操作建议使用方法一base64编码转为图片在线网址https://imgtobase64.d777.com/方法一:使用hutool的HttpResponse方法1.1引入依赖<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artif......
  • 字、字节、字符、编码方式
    参考文章:详解计算机中的字、字节(Byte)、比特(bit)及它们之间的关系字、字节字由若干个字节组成,一个字节是8个比特bit。字的位数叫做字长,即cpu一次处理二进制代码的位数。换算:1字节(Byte/byte)=8位(Bit/bit)1字符占用的字节不确定(不同的编码方式不同)1KB=1024Byte;1MB=1024KB。。。......
  • java 字符串中的编码和解码问题
     ......
  • java 字符流-编码
            ......
  • 推出稳定代码:人工智能辅助编码的新视野
    推荐:使用NSDT场景编辑器快速助你搭建可二次编辑的3D应用场景 在不断发展的软件开发环境中,对效率和可访问性的追求导致了各种工具和平台的创建。最新的创新之一是StableCode,这是StabilityAI的大型语言模型(LLM)生成AI产品。StableCode旨在帮助经验丰富的程序员和有抱负的开发......