Java笔记-字符串编码与解码以及编码表原理

编码表

编码表:是一张由字符及其对应编码的表

计算机只能识别二进制数据,早期由电信号演化而来。

为了方便使用计算机,让它可以识别各个国家的文字,就将各个国家的文字用数字来表示,并一一对应,形成一张编码表。


常见编码表


ASCII表

ASCII表:英国标准信息交换码。用一个字节的7位来表示字符,还有一个符号位。


ISO8859-1表

ISO8859-1表:拉丁码表。欧洲码表。用一个字节的8位表示。不支持中文。


GB2312表

GB2312表:中国的中文编码表。

GB 2312标准共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时,GB 2312收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。

但是!对于人名、古汉语等方面出现的罕用字,GB 2312不能处理,这导致了后来GBK及GB 18030汉字字符集的出现。


GBK表

GBK表:中国的中文编码表 GB2312 的升级,融合了更多的中文文字符号。

GBK 总计 23940 个码位,共收入 21886 个汉字和图形符号,其中汉字(包括部首和构件)21003 个,图形符号 883 个。


GB18030表

GB18030表:GBK的取代版本,也是中文目前的通用版本。

GB18030表:分为两个版本 GB18030-2000表GB18030-2005表

GB18030-2000收录了27533个汉字,GB18030-2005收录了70244个汉字。


BIG-5表

BIG-5码:通行于台湾、香港地区的一个繁体编码方案,俗称—–”大五码”。


Unicode表

Unicode表:国际标准码,融合了多种文字。

所有文字都用两个字节来表示

Java语言使用的就是Unicode码表


UTF-8表

UTF-8表:最多用三个字节来表示一个字符。

UTF-8是 Unicode 的升级版。它定义了一种”区间规则”,这种规则可以和 ASCII 编码保持最大程度的兼容:

它将Unicode编码为 00000000-0000007F的字符,用1字节来表示。
它将Unicode编码为 00000080-000007FF的字符,用2字节来表示。
它将Unicode编码为 00000800-0000FFFF的字符,用3字节来表示。


字符串的编码与解码


字符串编码解码介绍

字符串编码:将看得懂的字符变成计算机能看懂的符号(人类看不懂)。

Java字符串编码

方法名称 使用
byte[] getBytes() 使用当前平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。

Java字符串解码

方法名称 使用
String String(byte[] bytes) 通过使用当前平台默认字符集,解码指定的 byte 数组,构造一个新的 String。

其中当前平台,指的是当前操作系统。

我的是WIN10系统,默认的是GBK编码表。


字符串编码解码演示

public static void main(String[] args) {
    // 使用GBK编码,上面介绍过了,我的默认GBK
    String str = "锄禾日当午,汗滴禾下土";
    byte[] bs = str.getBytes();
    for (int i = 0; i < bs.length; i++) {
        System.out.print(bs[i] + " ");
    }
    System.out.println();
    // 使用GBK解码
    String newStr = new String(bs);
    System.out.println(newStr);
}
//运行结果为:
//-77 -6 -70 -52 -56 -43 -75 -79 -50 -25 44 -70 -71 -75 -50 -70 -52 -49 -62 -51 -63 
//锄禾日当午,汗滴禾下土


//其中每两个负数组成一个汉字,由于我的逗号为英文逗号,是44,可以刨除
//(-77 -6)锄 (-70 -52)禾 ...

在 GBK 中,所有汉字被拆分成两个字节,第一个字节肯定是负数,第二个字节不一定。所以用 new String(byte[] bytes) 解码时,看到第一个是负数的字节,就自动将后面一个字节跟前面的字节,放到一起处理。


字符串乱码问题

方法名称 作用
byte[] getBytes(String charsetName) 使用指定编码表去编码

字符串乱码演示:

public static void main(String[] args) {
    try {
        String str = "锄禾日当午,汗滴禾下土";
        byte[] bs = str.getBytes("Iso8859-1");
        System.out.println(Arrays.toString(bs));
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
}
//结果:
//[63, 63, 63, 63, 63, 44, 63, 63, 63, 63, 63]

//63在ASCII中对应'?'所以编码失败,因为iso8859-1不支持中文!

//扩展1:iso不区分大小写
//扩展2:异常名称UnsupportedEncodingException:
// 不被支持的编码名称
// 也就是怕你把编码名称给写错了

public static void main(String[] args) {
    try {
        String str = "锄禾日当午,汗滴禾下土";
        //编码 UTF-8
        byte[] bs = str.getBytes("UTF-8");
        System.out.println(Arrays.toString(bs));
        //解码 当前系统默认 GBK
        String errorStr = new String(bs);
        System.out.println(errorStr);
        //解码 我们来指定 UTF-8
        String correctStr = new String(bs, "UTF-8");
        System.out.println(correctStr);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
}

//结果:
//[-23, -108, -124, -25, -90, -66, -26, -105, -91, -27, -67, -109, -27, -115, -120, 44, -26, -79, -105, -26, -69, -76, -25, -90, -66, -28, -72, -117, -27, -100, -97]
//閿勭鏃ュ綋鍗?,姹楁淮绂句笅鍦?
//锄禾日当午,汗滴禾下土

乱码原因:
字符串编码与解码所依据的编码表不一致!导致了码表转换!统一解码编码表即可解决。

猜你喜欢

转载自blog.csdn.net/u011753266/article/details/82629357
今日推荐