常见编码问题

最近工作主要使用的python和java,之前比较少遇到过的编码问题开始浮现出来,再加上自己曾经写过的一个UDF使用的参数被我从java默认的byte[]调成了String,也给自己埋了个大坑。所以解决这些问题之后感觉有必要把编码的问题理一下,避免重蹈覆辙。

常见的编码有 ASCII, unicode, utf-8, ISO-8859-1 等

ASCII 是对应了128个字符,在字节中的第一位全部是0,对应的是英文字符,标点和阿拉伯数字,因此在使用时比较有限,不能够显示很多所需要的字符。ASCII码是python的默认编码方式

1
2
3
import sys
sys.getdefaultencoding()
# 'ascii'

之后,EASCII 成为ASCII码的补充,将字符数量从128增加到256, 扩充的字符包括表格符号,计算符号,希腊字母和特殊的拉丁字符。但表示的字符仍然有限。
另外,ISO-8859-1也是256个字符范围内的编码方式,这种编码与ASCII在前128位保持兼容一致,后面主要补充了拉丁字母,供欧洲使用。但从wiki的图中可以发现,ISO-8859-1并非在256个字符中能够一一对应,图中的绿色部分是没有字符表示的。 目前java在从String转成Byte[]的时候,使用的getbyte[charset]的方法,如果charset未定义则使用默认的ISO-8859-1

以上的三种编码方法都是对应的在一个字节中表示字符,显然,他们都不能对大部分的非英文字符完全表示出来。因此引入了unicode。
unicode 采用多字节进行编码,大大的增加了可表示字符的范围,且unicode可以很好的兼容ISO-8859-1的所有字符。中文也都可以通过unicode表示出来。unicode目前支持的字符还在不断的扩大,目前实际应用的统一码版本对应的UCS-2,使用两个字节表示字符,即65536个字符。
unicode的编码方式和实现方式是不同的,一个字符的unicode是一定的,但在传输过程中为了解决传输字节数,采用了不同的实现方式。

UTF-8 就是最为主要的一种实现方式。通过变长编码,可以将大部分的unicode在两个字节内完成编码,节省了传输资源。具体的前缀码实现在wiki中介绍的很清楚。