关于字符集、编码字符、字符编码方式的一些概念

1.基本概念

字符集:
字符的集合,带有特殊语义的符号,是人类的沟通方式的书面化,例如以前的甲骨文,后来的汉字。

编码字符集:
将一个数值赋值给字符的集合,一个字符对应一个会是多个数值,,常见的就是unicode,gbk,iso8859-1等

字符编码方式:
编码字符集到8位字节的映射,字符编码方式就是将字符编码的序列转化为字节序列,更通俗的说就是将数值转化为二进制码,计算机化,转化为计算机可以识别的0和1

总结的说字符集是沟通方式的抽象,编码字符集是对于字符集的映射(解决what问题),字符编码方式是解决映射后数据的解析(也可以认为是解决how的问题)

2.什么时候使用字符编码?

一般在进行网络传输或是文件存储的时候,需要使用字符编码,字符编码方式不等同于编码字符集,是映射,但两者关系又非常密切,所以大多数时候可以等同于同一个!比如GBK即是说字符集,也是字符编码方式,当然也有例外。
unicode原字符编码集对应了两种字符编码方式:UTF-8,UTF-16。

3.为什么会出现这两种?

我们知道对于一个英文字符我们采用一个字节存储是绰绰有余,但若采用两个字节就难免有些浪费了,同时中国的一些汉字又超过了2两个字节的表示范围,所以必须使用到三个字节及以上。所以最早出现的是UTF-16,后来UTF-16的编码方式导致了一些问题,后来又出现了UTF-8,两者的区别呢?

4.UTF-8和UTF-16的区别

UTF-8:是一种变长编码,第一个字节的最高位如果是0,则表示这个字符用单个字节表示,否则,从这一位开始向后数,有多少个连续的1,这个字符就用多少个字节表示。于是,英文字符只需要1个字节就可以表示,而中文字符一般需要3个字节来表示。

UTF-16:是定长编码,所有的字符都是两个字节进行表示,当然会出现超过两个字节范围的情况,它就必须扩容两个字节来进行表示,多出来的这两个字节称为代理对!所以若是采用UTF-16的字符编码方式,汉字的话会出现四个字节!

还有,对于字我们除了字本身之外,还会包含一些字体,字形等信息,这个就是通过编码字符集的属性来表示,看看unicode。
unicode包含三个属性:
1.Unicode Property 对于字符的功能进行分类,一个字符只属于一个Unicode Property,例如用\p{P}表示任何标点字符
2.Unicode Block 对字符进行分块,不同语系的字符就会落在同一块上,例如 \p{InCJK_Unified_Ideographs}表示兼容CJK(中文、日文、韩文)统一表意字符
3.Unicode Script 按照字符所属的书写系统来划分Unicode字符,例如 \p{Han}表示汉语(中文字符)
回到我们的java代码上看,Charset就是对应了编码字符集,对于字符集是不区分大小写!

UTF-16存在三种编码方式:
UTF-16BE :16-位UCS转换格式,高位字序。每个Unicode字符都被编码为2-字节序列,首先编写高序位8位(bit)。
UTF-16LE :16-位UCS转换格式,低位字序。每个Unicode字符都被编码为2-字节序列,首先编写低序位8位(bit)。
UTF-16 :16-位UCS转换格式。字序由可选的字序标记确定。UTF-16字符在RFC2781中指定。UTF-16BE和UTF-16BE格式编码成16-位,因而由字序确定。UTF-16是可移植编码,它使用导向字节标记来表示编码字节流的其余部分是否是UTF-16BE或UTF-16LE。

上面提到了字符集对应的是Charset,那么编码方式对应的就是CharsetEncoder和CharsetDecoder,这两个类实现如何对字符转化为字节序列及将字节序列转化为字符。
JDK现在默认采用的字符编码方式是UTF-16。

5.总结:

Charset(字符集类) 封装编码的字符集编码方案,用来表示与作为字节序列的字符集不同的字符序列。
CharsetEncoder(字符集编码类)
编码引擎,把字符序列转化成字节序列。之后字节序列可以被解码从而重新构造源字符序列。
CharsetDecoder(字符集解码器类)
解码引擎,把编码的字节序列转化为字符序列。
CharsetProvider SPI(字符集供应商SPI)
通过服务器供应商机制定位并使Charset实现可用,从而在运行时环境中使用。

作者: inter12

在这苦短的人生中,追求点自己的简单快乐

发表评论

电子邮件地址不会被公开。 必填项已用*标注