字符集 (ASCII、GBK、UTF-8、编码方案,解码方案、乱码等问题)

常见字符集 (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
      的字符。

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 10xxxxxx2个字节:第一个字节前3位为110,第二个字节前2位位10
1110xxxx 10xxxxxx 10xxxxxx3个字节:第一个字节前4位为1110,第2个字节和第3个字节前2位都位10
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx4个字节:第一个字节前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

    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值