UCS-2 UCS-4_ucs-2 big endian-程序员宅基地

介绍Unicode之前,首先要讲解一些基础知识。虽然跟Unicode没有直接的关系,但想弄明白Unicode,没这些还真不行。

字节和字符的区别

咦,字节和字符能有什么区别啊?不都是一样的吗?完全正确,但只是在古老的DOS时代。当Unicode出现后,字节和字符就不一样了。

字节(octet)是一个八位的存储单元,取值范围一定是0~255。而字符(character,或者word)为语言意义上的符号,范围就不一定了。例如在UCS-2中定义的字符范围为0~65535,它的一个字符占用两个字节。

Big Endian和Little Endian

上面提到了一个字符可能占用多个字节,那么这多个字节在计算机中如何存储呢?比如字符0xabcd,它的存储格式到底是 AB CD,还是 CD AB 呢?

实际上两者都有可能,并分别有不同的名字。如果存储为 AB CD,则称为Big Endian;如果存储为 CD AB,则称为Little Endian。

具体来说,以下这种存储格式为Big Endian,因为值(0xabcd)的高位(0xab)存储在前面:

地址
0x00000000 AB
0x00000001 CD

相反,以下这种存储格式为Little Endian:

地址
0x00000000 CD
0x00000001 AB

UCS-2和UCS-4

Unicode是为整合全世界的所有语言文字而诞生的。任何文字在Unicode中都对应一个值,这个值称为代码点(code point)。代码点的值通常写成 U+ABCD 的格式。而文字和代码点之间的对应关系就是UCS-2(Universal Character Set coded in 2 octets)。顾名思义,UCS-2是用两个字节来表示代码点,其取值范围为 U+0000~U+FFFF。

为了能表示更多的文字,人们又提出了UCS-4,即用四个字节表示代码点。它的范围为 U+00000000~U+7FFFFFFF,其中 U+00000000~U+0000FFFF和UCS-2是一样的。

要注意,UCS-2和UCS-4只规定了代码点和文字之间的对应关系,并没有规定代码点在计算机中如何存储。规定存储方式的称为UTF(Unicode Transformation Format),其中应用较多的就是UTF-16和UTF-8了。

UTF-16和UTF-32

UTF-16

UTF-16由RFC2781规定,它使用两个字节来表示一个代码点。

不难猜到,UTF-16是完全对应于UCS-2的,即把UCS-2规定的代码点通过Big Endian或Little Endian方式直接保存下来。UTF-16包括三种:UTF-16,UTF-16BE(Big Endian),UTF-16LE(Little Endian)。

UTF-16BE和UTF-16LE不难理解,而UTF-16就需要通过在文件开头以名为BOM(Byte Order Mark)的字符来表明文件是Big Endian还是Little Endian。BOM为U+FEFF这个字符。

其实BOM是个小聪明的想法。由于UCS-2没有定义U+FFFE,因此只要出现 FF FE 或者 FE FF 这样的字节序列,就可以认为它是U+FEFF,并且可以判断出是Big Endian还是Little Endian。

举个例子。“ABC”这三个字符用各种方式编码后的结果如下:

UTF-16BE 00 41 00 42 00 43
UTF-16LE 41 00 42 00 43 00
UTF-16(Big Endian) FE FF 00 41 00 42 00 43
UTF-16(Little Endian) FF FE 41 00 42 00 43 00
UTF-16(不带BOM) 00 41 00 42 00 43

Windows平台下默认的Unicode编码为Little Endian的UTF-16(即上述的 FF FE 41 00 42 00 43 00)。你可以打开记事本,写上ABC,然后保存,再用二进制编辑器看看它的编码结果。

notepad-encode.png

另外,UTF-16还能表示一部分的UCS-4代码点——U+10000~U+10FFFF。表示算法比较复杂,简单说明如下:

  1. 从代码点U中减去0x10000,得到U'。这样U+10000~U+10FFFF就变成了 0x00000~0xFFFFF。 
  2. 用20位二进制数表示U'。 U'=yyyyyyyyyyxxxxxxxxxx 
  3. 将前10位和后10位用W1和W2表示,W1=110110yyyyyyyyyy,W2=110111xxxxxxxxxx,则 W1 = D800~DBFF,W2 = DC00~DFFF。

例如,U+12345表示为 D8 08 DF 45(UTF-16BE),或者08 D8 45 DF(UTF-16LE)。

但是由于这种算法的存在,造成UCS-2中的 U+D800~U+DFFF 变成了无定义的字符。

UTF-32

UTF-32用四个字节表示代码点,这样就可以完全表示UCS-4的所有代码点,而无需像UTF-16那样使用复杂的算法。与UTF-16类似,UTF-32也包括UTF-32、UTF-32BE、UTF-32LE三种编码,UTF-32也同样需要BOM字符。仅用'ABC'举例:

UTF-32BE 00 00 00 41 00 00 00 42 00 00 00 43
UTF-32LE 41 00 00 00 42 00 00 00 43 00 00 00
UTF-32(Big Endian) 00 00 FE FF 00 00 00 41 00 00 00 42 00 00 00 43
UTF-32(Little Endian) FF FE 00 00 41 00 00 00 42 00 00 00 43 00 00 00
UTF-32(不带BOM) 00 00 00 41 00 00 00 42 00 00 00 43

UTF-8

UTF-16和UTF-32的一个缺点就是它们固定使用两个或四个字节,这样在表示纯ASCII文件时会有很多00字节,造成浪费。而RFC3629定义的UTF-8则解决了这个问题。

UTF-8用1~4个字节来表示代码点。表示方式如下:

UCS-2 (UCS-4) 位序列 第一字节 第二字节 第三字节 第四字节
U+0000 .. U+007F 00000000-0xxxxxxx 0xxxxxxx      
U+0080 .. U+07FF 00000xxx-xxyyyyyy 110xxxxx 10yyyyyy    
U+0800 .. U+FFFF xxxxyyyy-yyzzzzzz 1110xxxx 10yyyyyy 10zzzzzz  
U+10000..U+1FFFFF 00000000-000wwwxx-
xxxxyyyy-yyzzzzzzz
11110www 10xxxxxx 10yyyyyy 10zzzzzz

可见,ASCII字符(U+0000~U+007F)部分完全使用一个字节,避免了存储空间的浪费。而且UTF-8不再需要BOM字节。

另外,从上表中可以看出,单字节编码的第一字节为[00-7F],双字节编码的第一字节为[C2-DF],三字节编码的第一字节为[E0-EF]。这样只要看到第一个字节的范围就可以知道编码的字节数。这样也可以大大简化算法。



而记事本的ANSI编码,就是这种默认编码,所以,一个中文文本,用ANSI编码保存,在中文版里编码是GBK模式保存的时候,到繁体中文版里,用BIG5读取,就全乱套了。 记事本也不甘心这样,所以它要支持Unicode,但是有一个问题,一段二进制编码,如何确定它是GBK还是BIG5还是UTF-16/UTF-8?记事本的做法是在TXT文件的最前面保存一个标签,如果记事本打开一个TXT,发现这个标签,就说明是unicode。标签叫BOM,如果是0xFF 0xFE,是UTF16LE,如果是0xFE 0xFF则UTF16BE,如果是0xEF 0xBB 0xBF,则是UTF-8。如果没有这三个东西,那么就是ANSI,使用操作系统的默认语言编码来解释。 Unicode的好处就是,不论你的TXT放到什么语言版本的Windows上,都能正常显示。而ANSI编码则不能。(UTF-8的好处是在网络环境下,比较节约流量,毕竟网络里英文的数据还是最多的)


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_34480269/article/details/102836365

智能推荐

OpenWrt 4G路由器检测上网,然后开启 WIFI的脚本_wifi路由器脚本-程序员宅基地

文章浏览阅读1.3k次。OpenWrt 4G路由器检测上网,然后开启 WIFI的脚本MT7620A 4G的路由器刷了OpenWrt系统,为了实现4G在线开启WIFI 功能,否则关闭WIFI,首先在系统设置当中默认关闭WIFI功能,接下来建立一个Shell脚本,如下:#!/bin/bash#此脚本用于检测能否上网,是则开启WIFI功能,否则关闭。#建议用定时任务执行此脚本,如每分钟执行一次,也可修改此脚本用于死循环..._wifi路由器脚本

MFC程序崩溃的友好处理-程序员宅基地

文章浏览阅读69次。软件总存在这样或者那样的bug。虽然测试员已经在很努力的寻找问题,程序员也在汗流浃背的除虫,但是总会有一些情况被遗漏或者不可预测,比如用户的硬件环境、网络状况、操作系统差异等等,不一而足。而导致的结果则是弹出下面这样一个让用户摸不着头脑又恼火的提示,然后崩溃掉,令程序员尴尬不已。而在一些成熟的软件产品中,程序崩溃时我们看到的却是另外一番画面,比如QQ:又比如迅雷:..._mfc程序出现 appcrash

【计算机组成实验】四位加法器_四位串行进位加法器-程序员宅基地

文章浏览阅读7.5k次,点赞2次,收藏34次。并行地形成各级进位,各进位之间不存在依赖关系,因而这种方式也称为先行进位、同时进位或跳跃进位。_四位串行进位加法器

selenium对元素进行操作(三):日期控件处理_selenium日期控件处理-程序员宅基地

文章浏览阅读7.6k次,点赞3次,收藏36次。1分钟了解一个测开小知识:selenium对元素进行操作(三):日期控件处理如果日期控件支持输入,可以直接使用send_keys,按照文本框录入时间。但是大多数日期控件,都是这种格式<input type="text" autocomplete="off" readonly="readonly" placeholder="选择日期" class="aty-input aty-input-hasicon">控件的html描述是这样婶的。可以看到readonly="r_selenium日期控件处理

华为软开云新手使用过程-程序员宅基地

文章浏览阅读2.2k次。我们公司说是小公司,老板说每年资金进场很大,说是大公司,来来回回,人的流动性挺高的。公司有从华为出来的"大牛",姑且称之为大牛吧,说要为了规范我们项目开发的流程和代码的质量,极力推荐使用软开云。本人也是一头雾水,因为野惯了,还真不习惯,找了不少资料,终于部署成功和拉取和上传代码了。工作里面的需求什么的略过...1.代码要上传,需要先建立一个仓库,点击下面的代码托管,再点击普通新建,为什..._软开云

计算机网络基础知识点-程序员宅基地

文章浏览阅读7k次,点赞5次,收藏54次。1.网络介绍由通信介质将地理位置不同、相互独立的计算机连接起来,实现数据和资源共享。2.网络分类2.1 按照拓扑结构分类1.总线型(一根线上串好多计算机)特点:两端信号终结器,分叉处有T型头2.环形网络效率很低,同一时间只有两个计算机通信,这两台计算机有其自己的令牌。3.星形线路利用率虽然高,但是线路单一,一旦坏了就少了一条线路。且中央节点压力大。 单点护照网络利用率高,但是中央节点压力大。2.2 按照地域分类1.局域网一个公司、一个家庭2.城域网一个区、一个城市、一个国家_计算机网络基础知识点

随便推点

多频外差_多频外差的程序-程序员宅基地

文章浏览阅读526次。% 程序开始clc;close all;clear;% 图片的初始化width = 1280; heigth = 800;% 三频率freq = [70 64 59];C = cell(3,4); for i=1:3 for j=1:4 C{i,j} = zeros(heigth,width); endend% 利用余弦函数计算12张图的灰度值% 图像的生成% 三种频率,四组相位for i = 1:3 % 对应三种不同的频率 _多频外差的程序

[每日一题] 11gOCP 1z0-052 :2013-09-9 PL/SQL package body...........................................A46_包规范和包体都能声明变量且声明的变量都是全局性的,即都可以在外部被访问到-程序员宅基地

文章浏览阅读2.6k次。[每日一题] 11gOCP 1z0-052 :2013-09-9 PL/SQL package body_包规范和包体都能声明变量且声明的变量都是全局性的,即都可以在外部被访问到

游戏玩家管理系统-程序员宅基地

文章浏览阅读2.6k次,点赞5次,收藏40次。实体类package com.stage3.haungzixiao.exam1.entity;public class Player { private Integer id; //玩家ID private String name; //玩家名称 private Integer level; //玩家等级 private String game;//游戏名称 private String time;//注册时间 private Integer st..._玩家管理系统

Vue2.x项目整合ExceptionLess监控_vue2使用exceptionless-程序员宅基地

文章浏览阅读177次。一直以来我们都是用Sentry做项目监控,不过前段时间我们的Sentry坏掉了(我搞坏的)但监控又是很有必要的,在sentry修好之前,我想先寻找一个临时的替代方案,同时发现网上关于ExceptionLess的资料少得可怜,ExceptionLess官方的文档也不是很完善,翻了好久文档和源码,于是有了本文……_vue2使用exceptionless

VS Code搭建Python开发环境_为什么没人用vs写python-程序员宅基地

文章浏览阅读1.5k次。VS Code(Visual Studio Code)是一个由微软开发的免费的跨平台代码编辑器,可以在Windows、Linux和macOS上运行。它支持多种编程语言和文件格式,并具有许多功能和插件,可以增强编辑器的功能。VS Code具有内置的调试器、Git版本控制、智能代码完成、代码片段和扩展等功能,可以提高开发人员的生产力和代码质量。它也是一个开源项目,并且有一个活跃的社区来支持和扩展它的功能。最近我又增加了GitHub Copilot插件,编程爽得简直不要不要的。_为什么没人用vs写python

Pytorch交叉熵损失(CrossEntropyLoss)函数内部运算解析_crossentropyloss(reduction="mean")-程序员宅基地

文章浏览阅读5.5k次,点赞2次,收藏17次。  对于交叉熵损失函数的来由有很多资料可以参考,这里就不再赘述。本文主要尝试对交叉熵损失函数的内部运算做深度解析。 1. 函数介绍  Pytorch官网中对交叉熵损失函数的介绍如下:CLASS torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=- 100,reduce=None, reduction=‘mean’, label_smoothing=0.0)  该损失函数计算输入和目标值之间的交叉熵损失。_crossentropyloss(reduction="mean")

推荐文章

热门文章

相关标签