Java 字符编码
转义字符
一些特殊字符。
转义字符 | 含义 |
---|---|
换行 | |
回车 | |
结束字符 | |
s | 空格 |
’ | 单引号 |
“ | 双引号 |
\ | 反斜杠 |
字符编码
ASCII
American Standard Code for Information Interchange,美国信息交换标准代码。
计算机发明之初,基本只考虑了美国的需求,美国大概只需要 128 个字符。
数字 32~126 表示的字符都是可打印字符。
0~31 和 127 表示一些不可打印的字符。
数字 | 缩写/字符 | 解释 | 转义字符 |
---|---|---|---|
0 | NUL(null) | 空字符 | |
8 | BS(backspace) | 退格 | |
9 | HT(horizontal tab) | 水平制表符 | |
10 | LF(NL line feed,new line) | 换行键 | |
13 | CR(carriage return) | 回车键 | |
27 | ESC | 换码 | |
127 | DEL(delete) | 删除 |
ASCII 码对美国够用,但对其他国家是不够的。
各国的计算机厂商发明了各自的编码方式以表示自己国家的字符,为了保持与 ASCII 码的兼容性,一般都是将最高位设置为 1。
就是说,当最高位为 0 时,表示 ASCII 码,当为 1 时就是各个国家自己的字符。
ISO 8859-1
ISO 8859-1 又称 Latin-1,同样使用一个字节表示一个字符。
其中 0~127 与 ASCII 一样,128~255 规定了不同的含义。
Windows-1252
基本上可以认为,ISO8859-1 已被 Windows-1252 取代,在很多应用程序中,即使文件声明它采用的是 ISO 8859-1 编码,解析的时候依然被当作 Windows-1252 编码。
GBK
GBK 使用固定的两个字节表示字符,高位字节范围是 0x81~0xFE ,低位字节范围是 0x40~0x7E 和 0x80~0xFE。
需要注意的是,低位字节是从 0x40(即64)开始的,因此低位字节的最高位可能为 0。
Unicode
Unicode 给世界上所有字符都分配了一个唯一的数字编号,编号范围从 0x000000~0x10FFFF。
每个字符都有一个 Unicode 编号,这个编号一般写成十六进制,在前面加 U+。
但它并没有规定这个编号怎么对应到二进制表示。
编号怎么对应到二进制表示?主要有 UTF-32、UTF-16 和 UTF-8 。
UTF-32
字符 Unicode 编号的整数二进制形式,4个字节。
UTF-16
UTF-16 使用变长字节表示。对于编号在 U+0000 ~ U+FFFF的字符(常用字符),直接用 2 个字节表示。编号在 U+10000 ~ U+10FFFF的字符(增补字符集),需要使用 4 个字节表示。
在 Java 内部进行字符处理时,采用的是 Unicode 编码,具体的编码格式是 UTF-16。
UTF-8
UTF-8 使用变长字节表示,字符使用的字节个数与其 Unicode 编号的大小有关,编号小的使用的字节就少,字节个数为 1~4 不等。
编号范围 | 二进制格式 |
---|---|
0x00 ~ 0x7F(0 ~ 127) | 0xxx xxxx |
0x80 ~ 0x7FF(128 ~ 2047) | 110x xxxx 10xx xxxx |
0x800 ~ 0xFFFF(2048 ~ 65535) | 1110 xxxx 10xx xxxx 10xx xxxx |
0x10000 ~ 0x10FFFF(65536以上) | 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx |
UTF-8 将字符看作整数,转化为二进制形式(去掉高位的 0),然后将二进制位从右向左依次填入对应的二进制格式 x 中,填充完后,如果对应的二进制格式还有没填的 x,则设为 0。
/*
如 "马" 的 Unicode 编号是 0x9A6C,整数编号是 39532,二进制 1001 101001 101100
对应的 UTF-8 二进制格式是:1110 xxxx 10xx xxxx 10xx xxxx
将二进制 1001 101001 101100 从右到左依次填入二进制格式中
结果就是其 UTF-8 编码:1110 1001 1010 1001 1010 1100
*/
UTF-8 是兼容 ASCII 的,对大部分中文字符而言,需要使用三个字节表示。
编码转换
不同编码格式之间可以借助 Unicode 编号进行编码转换。可以认为,每种编码都有一个映射表,存储 Unicode 编号和其特有的字符编码之间的对应关系。
编码转换的具体过程可以是:一个字符从 A 编码转到 B 编码,先找到字符的 A 编码格式,通过 A 编码的映射表找到其 Unicode 编号,然后通过 Unicode 编号再查找 B 编码的映射表,找到字符的 B 编码格式。
乱码问题
解析错误:使用错误的编码进行解析,如小明采用 Windows-1252 写了个文件,发送给了小红,小红 使用 GBK 来解析这个字符,看到的可能就是乱码。
编码转换错误:在错误解析的基础上还进行了编码转换。如上述,小红用 GBK 解析打开后看到乱码,又转换成了 UTF-8 编码。