文章目录
常见字符集 (ASCII、GBK、UTF-8、编码方案,解码方案、乱码等问题)
1.ASCII编码
-
当美国人发明计算机时,他们遇到了一个问题:要想让计算机来处理数据,首先得让计算机
能够存储美国人的文字,但是计算机是机器只能处理 0和1(二进制数) 两种信号,为此美
国人设计出了一套能够让计算机存储他们文字的编码(ASCII编码)。由于美国人的文字只
由数字(09)、26个字母(az,A~Z)、标点符号以及一些特殊字符组成,加起来总共127个字符,
于是美国人就给这127个字符进行编号:从0到127(0~127)。为了让计算机能够存储,他们就将
每个编号转换为对应二进制数,由于计算机存储数据的基本单位是字节,而1字节用8位二进制数
表示,而7位二进制数就可以表示0到127所有的字符,于是美国人就在每个字符编码前面加了一
位0,使其构成8位,至此美国人的文字在计算机中就用一位字节表示。 -
标准ASCII字符集
-
ASCII(American Standard Code for Information Interchange):美国信息交换标准代码,包括了英文符号等。
-
标准ASCII使用1字节存储一个字符,首位是0,总共可以表示128个字符,对美国佬来说完全够用。
-
2.GBK编码(汉子内码扩展规范,国标)
-
随着计算机的使用越来越广泛,当中国人看到美国人的编码(ASCII编码)时,说了一句:还不够我塞牙缝!
-
汉字编码字符集,包含2万多个汉字等字符,GBK中一个中文字符编码成两个字节的形式存储。
-
注意:GBK兼容了ASCII字符集。(这里提一句:因为计算机是美国人发明的,你要使用,就要听话,
遵守美国人制定的规则,所以需要兼容ASCII字符集) -
问题来了:如果英文数字用一个字节存储,汉字用两个字节存储,那么当一段文字中既有汉字也有英文
时,计算机是怎样识别的呢?- GBK规定:汉字的第一个字节的第一位必须是1。当计算机读取字节的时候发现该字节的第一位是1
时,计算机就认为这是一个汉字,于是计算机就连读取两个字节来表示一个汉字,当计算机读取字节
时发现第一位是0,计算机就认为这是一个ASCII的字符,于是计算机就只读取一个字节来表示为ASCII
的字符。
- GBK规定:汉字的第一个字节的第一位必须是1。当计算机读取字节的时候发现该字节的第一位是1
3.UTF-8编码
- 当计算机在全世界普及时,如果每个国家都来一个编码,比如:巴基斯坦码、迪拜码、岛国码、韩文码、
乌兹别克斯坦码、吉尔吉斯斯坦码、哈萨克斯坦码这么的编码时,会出现现一个很严重的问题:信息在各个国
家流通的时候,比如:韩文码用迪拜码打开时肯定会出现一个乱码的问题!这时,国际组织就站出来了,说:
你们都别整自己字符集了,我来给全世界国家整一套通用的字符集,叫Unicode字符集(统一码,也加万国码)
Unicode字符集(统一码,也加万国码)
-
Unicode是国际组织制定的,可以容纳世界上所有文字、符号的字符集。
-
Unicod字符集提供了很多编码方案,例如:UTF-32
-
UTF-32编码方案的思想是:简单粗暴,我用四个字节来存储一个字符,有容乃大。
-
但是UTF-32并没有被人们所接纳,因为人们觉得这种编码太 奢侈 了,美国人ASCII字符集本来一个字节
就可以存储但是用UTF-32就需要用四个字节,空出来3个字节用不到还多要3倍的存储空间,非常的浪费,就
是连中国人的汉字也没占到便宜,有两位字节用不到,还要多用1倍的存储空间。而且这样字符在通讯效率上
还会大大降低。 -
国际组织站出来看好像也是啊,于是国际组织又设计了一套改变字符苍生的新的编码方案:UTF-8
-
UTF-8编码方式
- 是Unicode字符集的一种编码方案吗,采取可边长方案,共分四个长度区:1字节,2字节,3字节,4字节
- 英文字符、数字等只占1个字节(兼容标准ASCI编码),汉字字符占用3个字节。
UTF-8编码方案 | 说明 |
---|---|
0xxxxxxx (ASCII码) | 1个字节:第一位为0 |
110xxxxx 10xxxxxx | 2个字节:第一个字节前3位为110,第二个字节前2位位10 |
1110xxxx 10xxxxxx 10xxxxxx | 3个字节:第一个字节前4位为1110,第2个字节和第3个字节前2位都位10 |
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 4个字节:第一个字节前5位为11110,后3个字节每个字节前2位都为10 |
-
其余位才用来存储具体的字符编码,从右开始排列
-
注意:
- 技术人员在开发的时候都应该使用UTF-8编码!
- 字符编码时使用的字符集,和解码时使用的字符集必须一致,否则会出现乱码
- 英文,数字一般不会乱码,因为很多字符集都兼容了ASCII编码。
4.java代码实现字符的编、解码
编码
String提供如下方法 | 说明 |
---|---|
byte[] getBytes() | 使用平台的默认字符集将该 String编码为一系列字节,将结果存储到新的字节数组中 |
byte[] getBytes(charsetName) | 使用指定字符集将该 String编码为一系列字节,将结果存储到新的字节数组中 |
import java.util.Arrays;
/*
使用java程序对字符进行编解码。
*/
public class Test {
public static void main(String[] args){
System.out.println("Hello World!");
//1.编码
String data = "a爱b";
byte[] bytes = data.getBytes(); // 默认是按照平台字符集(UTF-8)进行编码。
/*
输出结果:
[97, -26, -120, -111, 98]
解析:
[97, -26, -120, -111, 98]
a 我 b
在 utf-8编码 中英文占一个字节,中文占三个字节
*/
System.out.println(Arrays.toString(bytes));
//按指定的字符集进行编码。
byte[] bytes1 = data.getBytes("GBK");
/*
输出结果:
[97, -50, -46, 98]
解析:
[97, -50, -46, 98]
a 我 b
在 GBK编码 中英文占一个字节,中文占两个字节
*/
System.out.println(Arrays.toString(bytes1));
}
}
解码
String提供如下方法 | 说明 |
---|---|
String(byte[] bytes) | 使用平台的默认字符集将该 String编码为一系列字节,将结果存储到新的字节数组中 |
String(byte[] bytes, String charsetName) | 使用指定字符集将该 String编码为一系列字节,将结果存储到新的字节数组中 |
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/*
使用java程序对字符进行编解码。
*/
public class Test {
public static void main(String[] args) throws Exception {
//1.编码
String data = "a我b";
byte[] bytes = data.getBytes(); // 默认是按照平台字符集(UTF-8)进行编码。
System.out.println(Arrays.toString(bytes));
//按指定的字符集进行编码。
byte[] bytes1 = data.getBytes("GBK");
System.out.println(Arrays.toString(bytes1));
//2.解码
String s1 = new String(bytes); // 按照平台默认编码(UTF-8)解码。
System.out.println(s1); // 输出结果:a我b
//String s2 = new String(bytes1); //用平台默认的字符集(UTF-8)解码用GBK字符集编码的字符串
//System.out.println(s2); //输出乱码结果:a��b
String s2 = new String(bytes1,"GBK"); // 用与编码相同的字符集(GBK)来解码
System.out.println(s2); //输出结果:a我b
}
}