哈喽,大家好,我是指北君。
最近看《狂飙》了吧,大嫂气场十足!飒爽!
Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。Unicode是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符 设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
简介
- 什么是字符集?
字符集当然是字符的集合,那么字符呢?你看到这篇文章的每个字母、中文或标点符号,就是一个个字符。
在计算器出现的早期,计算机仅支持的字符集为ASCII,其对应的字符就能够满足当时的使用需求,但随着计算机的发展,在计算机上需要显示的内容越来越复杂, 各个国家不同厂商都有自己的实现标准,然而有没有谁能够兼容世界所有的文字,因此产生了各种字符集,比如ASCII、ISO-8859-1、GB2312、BIG5等等。
- 为什么要用字符编码?
为了实现人和计算机间的交流,我们只认识字符,计算机只认识二进制数据,字符编码即实现将字符转换成机器码进行存储、使用的的一种技术手段。
Unicode是字符集,而不是编码方式。
字符集
字母、文字、数字、标点符号、图形符号等字符的集合。表示了字符到二进制比特位的映射关系
ASCII
- 技术特征:7位(bits)表示一个字符,共128字符,字符值从0到127,其中32到126是可打印字符。
- 扩展字符集:7位编码的字符集只能支持128个字符,为了表示更多的欧洲常用字符对ASCII进行了扩展,ASCII扩展字符集使用8位(bits)表示一个字符,共256字符。ASCII扩展字符集:它是从ASCII字符集扩充出来的,扩充后的符号增加了表格符号、计算符号、希腊字母和特殊的拉丁符号。
GB2312
- GB2312是中国国家标准的简体中文字符集。它所收录的汉字已经覆盖99.75%的使用频率,基本满足了汉字的计算机处理需要。在中国大陆和新加坡获广泛使用。
- 技术特征(1)分区表示:GB2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示方式也称为区位码。各区包含的字符如下:01-09区为特殊符号;16-55区为一级汉字,按拼音排序;56-87区为二级汉字,按部首/笔画排序;10-15区及88-94区则未有编码。(2)双字节表示 两个字节中前面的字节为第一字节,后面的字节为第二字节。习惯上称第一字节为“高字节” ,而称第二字节为“低字节”。“高位字节”使用了0xA1-0xF7(把01-87区的区号加上0xA0),“低位字节”使用了0xA1-0xFE(把01-94加上0xA0)。
- UnicodeUnicode是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。Unicode 标准始终使用十六进制数字,而且在书写时在前面加上前缀“U+”,例如字母“A”的编码为 0x0041 和字符“€”的编码为 0x20AC,所以“A”、“€”的编码书写为“U+0041”、“U+20AC”。
字符集编码
字符对应二进制字节表示后的编码规则以及存储形式。
- ASCII
- GB2312
- UTF-8
ASCII、GB2312 是字符集也是字符编码
unicode
- 5层模型
Unicode编码模型包含五层:
层次 | 名称 | 作用 | 结果 | 描述 |
1 | 抽象字符表ACR | 字符范围 | ||
2 | 编号字符集CSS | 字符编号 | unicode字符集 | |
3 | 字符编码方式CEF | 码元序列 | UTF-8、UTF-16、UTF-32 | |
4 | 字符编码方案CES | 物理编码 | 字节序列 | |
5 | 传输编码语法TES | 网络传输编码 | base64 |
- Unicode字符集被划分基本多文种平面、辅助平面,共17个平面(或17个区,编号为 0-16 ),每个平面有 216即65536个码点, 共65536*17=1,114,112个码点
- 码点空间范围为U+000000 ~ U+10FFFF。
- 每个码点对应一个字符(有些属于非字符或被保留码点),但是一个字符可能有多个码点(比如å)
- unicode编码有UTF8、UTF16、UTF32,分别最少需要1、2、4个字节来存储一个字符编码
unicode是字符的表现形式,而utf8是字符的存储形式,或者说是存储实现
unicode和utf8
下面是unicode与unf8的映射表,我们通过字符的unicode码点(对应的16进制编码)可以找到对应的utf-8格式并进行编码转换最终实现物理存储。
unicode | utf-8 |
000000-00007F | 0xxxxxxx |
000080-0007FF | 110xxxxx 10xxxxxx |
000800-00FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
010000-10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
那么unicode字符如何转换成utf8编码呢?
- 比如“我”对应unicode为 \u6211,可以通过该网站查询到
- 转换为二进制后:01100010 00010001
- 根据上表的取值范围可以确定为:000800-00FFFF - 1110xxxx 10xxxxxx 10xxxxxx
- 通过转换后结果为:11100110 10001000 10010001
- 转换为16进制为:E6 88 91,可以通过UE这样的编辑工具,切换成16进制模式,可以看到“我”转换后的编码也是这个
有没想过,像GBK为什么既可以是字符集又可以是字符编码?其实将字符映射成对应的二进制数据时,我们是可以将其直接存储到计算机,但unicode作为统一码,基本攘括了目前常用的所有的字符,而这些字符不是都由两个字节组成,比如前面说的å,那么如何确定一个字符到此从哪个字节开始呢?这里引用utf编码就是为了实现这个,不仅减少了字符空间占比,同时提高了字符编码效率。
BOM
BOM 是 Byte Order Mark 的缩写。是UTF编码方案里用于标识编码的标准标记,在UTF-16里本来是FF FE,变成UTF-8就成了EF BB BF。这个标记是可选的, 因为UTF8字节没有顺序,所以它可以被用来检测一个字节流是否是UTF-8编码的。
Java中的unicode
在java中,我们通过\u开头来表示unicode编码,比如上面的\u6211,则表示的是“我”。
看下面这段代码,你觉得会输出什么?
当然是“Hello World”了,不要觉得//后面的代码全部会被解析为注释,前提是没有换行符,然而\u000d恰好会被解释为换行符,这样其后面的代码会作为新的一行进行解析, 这也是为什么会有这样的输出结果了
通过下面的命令可以对java源文件进行编译:
javac ./Main.java -encoding utf-8
window环境默认编码为gbk
要知道java作为一门高级静态语言,需要通过编译后才能交由JVM加载使用的,在java文件编译前还会经历对源代码进行词法分析、语法分析、语义分析等等,最后生成class文件后,才能被JVM加载。而源文件中\u开头的字符则是在这个过程中被解析并处理的。
结束语
unicode作为世界统一编码,经历了很多变革,该篇主要通过unicode让你对字符集以及字符编码有一个简单的认识。