Java学习笔记之IO(十六):编码和解码

package com.io.g_sequence;

import java.util.Arrays;

import org.junit.Test;

/*

编码与解码:

	编码:把看得懂的字符变成看不懂的码值,这个过程叫做编码;
	
	解码:把码值根据码表查找到对应的看得懂的字符,这个过程叫做解码;
	


码表:可以把码表看成两列的表格,一列是字符,一列是码值;例如:a-97;   a就是字符,97就是码值;

最先出现的是ASCII码表,也叫美国标准信息交换码表,是用一个字节的7位表示;
一个字节有8位,即2^8=256(表示范围-128~127),所以一个字节可以表示256个字符;但是美国没有那么多字符,他用不完256个字符,
所以只用了一个字节的前7位,即最大为 01111111(127);也就是说,ASCII码表中存在一些空格,即有一些数字没有对应的字符;

之后,欧洲也发明了自己的码表,叫做ISO8859-1码表,也叫作拉丁码表,用一个字节的8位表示;又称Latin-1(拉丁编码)或"西欧语言";
由于ASCII码表包含的仅仅是英文字母,并没有完全占满256个编码位置,所以它以ASCII为基础,在空置的 0xA0-0xFF 的范围内,加入
192个字母及符号,藉以供使用变音符号的拉丁母语言使用;从而支持德文、法文等;它依然是一个单字节编码,只是比ASCII更全面;
ISO8859-1是唯一一个将码表中的所有位置都占满的码表,即在ISO8859-1码表中每一个数字都对应了一个字符;

然后,中国发明了自己的码表,即GB2312码表;在这个码表中,英文占一个字节,中文占两个字节;由于中文汉字较多,256个编码位置已经
不能够满足中文编码了,所以中文占了两个字节的位置,即2^16=65536;不过,GB2312的65536个编码位置也没有用完,还存在一些空位;
GB2312码表最初被发明的时候,并不是很完善,有很多生僻字没有加入到该码表中,于是后来对GB2312码表进行了升级,融合了更多的中文
文字符号,升级后的码表就是GBK码表;

后来,由于每个国家都使用每个国家自己的码表,用起来很麻烦,很混乱,这时候就有人提出来一种规范,一种全世界通用的编码规范,叫做Unicode;
unicode也叫“国际标准码规范”,融合了多种文字,所有文字都用两个字节来表示,java语言使用的就是unicode;不过,Unicode不是码表,
它只不过是代表了一个规范,如果哪个码表实现了Unicode规范,那么这个码表就必须要容纳全世界所有的文字;后来,在这个规范下就出现了
UTF-8码表,也就是说UTF-8码表是Unicode规范的一种实现;在这个码表中英文占一个字节,中文占三个字节;

在Unicode规范下面,还有一个码表,叫做UTF-16码表;在这个码表中英文和中文都是占两个字节;

使用最多的是ISO8859-1、GBK、UTF-8;
使用什么样的编码写数据,就要使用什么样的编码读取数据,不然就会出现乱码;

 */

public class Demo6 {

	// 编码
	@Test
	public void test1() throws Exception{
		String str = "中文";
		
		// 使用平台默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
		// 平台默认的编码表是GBK码表,一个中文占四个字节;编码过程;
		byte[] buf = str.getBytes();	
		// 编码结果:[-42, -48, -50, -60]
		System.out.println("编码结果:" + Arrays.toString(buf));
		
		
		// getBytes()也可以自己指定编码格式:utf-8码表中一个汉字占三个字节;
		byte[] b = str.getBytes("UTF-8");
		// 编码结果:[-28, -72, -83, -26, -106, -121]
		System.out.println("编码结果:" + Arrays.toString(b));
	}
	
	// 解码
	@Test
	public void test2() throws Exception{
		String str = "中文";
		
		// 使用平台默认字符集进行编码
		byte[] buf = str.getBytes();
		// 编码结果:[-42, -48, -50, -60]
		System.out.println("编码结果:" + Arrays.toString(buf));
		
		// 使用平台默认字符集进行解码;因为编码和解码使用的码表一样,所以可以解码成功;
		String s = new String(buf);
		System.out.println("解码结果:" + s);	// 解码结果:中文
		
		
		System.out.println("----------------");
		
		
		// 如果编码和解码使用不同的字符集,则解码失败
		// 指定编码格式为 utf-8
		byte[] buf2 = str.getBytes("utf-8");
		// 编码结果:[-28, -72, -83, -26, -106, -121]
		System.out.println("编码结果:" + Arrays.toString(buf2));
		
		// 解码时使用平台默认字符集(GBK) 
		String s2 = new String(buf2);
		System.out.println("解码结果:" + s2);	// 解码结果:涓枃
		
		// 指定解码时也使用utf-8
		String s3 = new String(buf2, "utf-8");
		System.out.println("解码结果:" + s3);	// 解码结果:中文
	}
	
	@Test
	public void test3() throws Exception{
		String str = "a中文";
		
		// 如果编码与解码时指定的是unicode,实际上就是使用的utf-16码表;
		byte[] buf = str.getBytes("unicode");
//		byte[] buf = str.getBytes("utf-16");	// 两种写法编码结果一样;
		
		// 编码结果:[-2, -1, 0, 97, 78, 45, 101, -121]
		// 问题:既然unicode编码 英文和汉字都是占两个字节,为什么编码结果出现8个字节?
		// 因为unicode编码有一个标志位,即最前面的[-2,-1],这两个标志位没有任何实际意义,他只是用来说明
		// 此编码结果是通过我unicode实现的;
		System.out.println("编码结果:" + Arrays.toString(buf));
	}
	
	@Test
	public void test4() throws Exception{
		String str = "大家好";
		
		// 使用平台默认字符集进行编码(GBK)
		byte[] buf = str.getBytes();
		// 编码结果:[-76, -13, -68, -46, -70, -61]
		System.out.println("编码结果:" + Arrays.toString(buf));
		
		// 使用ISO8859-1进行解码
		str = new String(buf, "ISO8859-1");
		System.out.println("解码结果:" + str); 	// 解码结果:?ó????
		
		// 问题:编码之后字节数组的内容为:[-76, -13, -68, -46, -70, -61],而ISO8859-1码表中每一个
		// 数字都对应着一个字符,那么解码的结果应该为 6个不同的字符才对,为什么会出现 5个相同的?
		// 因为ISO8859-1中有很多特殊的符号,不能在控制台上进行显示,所以只能用?进行代替;
		// 通过断点watch可以查看ISO8859-1解码出来的字符值:[´, ó, ¼, Ò, º, Ã]
		
		
		// 需求:将通过ISO8859-1解码出来的乱码重新还原成中文
		// 1、先将乱码通过ISO8859-1重新进行编码;
		byte[] b = str.getBytes("ISO8859-1");
		System.out.println("重新编码:" + Arrays.toString(b));
		// 2、然后再使用平台默认字符集进行解码(gbk)
		str = new String(b);
		System.out.println("重新解码:" + str);
		
		// 问题:所有的乱码都可以被还原吗?
		// 并不是所有的乱码都可以被还原;通过ISO8859-1解出来的乱码之所以能被还原,是因为ISO8859-1这个码表每一个数字
		// 都有对应的一个字符;生成乱码字符之后,可以反向根据码表去找到对应的数字,然后再进行还原;而其他码表的编码位置并
		// 没有完全被占用,即有些数字没有对应的字符,所以当解码时可能会出现有些数字找不到对应的字符,此时就会返回一个未知字符,
		// 那么原来的字符数字就会被丢弃,从而无法进行还原;
	}
	
}

猜你喜欢

转载自blog.csdn.net/qq_29331365/article/details/78214606
今日推荐