Java学习中遇到的编码问题

问题源头:网看编码相关视频,一个测试用例查看“慕A”字符串的2进制编码。当时不理解为什么要加上b&0xff这条语句

public class EncodeTest {
	public static void main(String[] args) throws Exception {
		String s = "慕A";
		byte[] bytes = s.getBytes();
		for (byte b : bytes) {
			System.out.print(Integer.toBinaryString(b & 0xff) + "       ");
		}
		System.out.println();
		for (byte b : bytes) {
			System.out.print(Integer.toBinaryString(b) + "       ");
		}
	}
}



分别测试b和b&0xff结果如下:

由这个小问题引出1个问题:

编码的问题

1.1 ASCII编码

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电

脑编码系统。它主要用于显示现代英语,而其扩展版本EASCII则可以勉强显示其他西欧语言

ASCII编码:将ASCII字符集转换为计算机可以接受的数字系统的数的规则。使用7位(bits)表示一个字符,共128字符;但是7位编码的字符集只能支持128个字符,为了表式更多的欧洲常用字符对ASCII进行了扩展,ASCII扩展字符集使用8位(bits)表示一个字符,共256字符。

      在测试程序中的A就是符合ASCII编码规则即:01000001

   1.2 GBXXXX编码

       很明显仅仅通过ASCII编码根本无法表示我天朝的7000多常用汉字,于是出现用两个字节进行编码同时兼容ASCII编码的GBxxxx系列编码方式,这类编码方式仅适用于中文加上原有的ASCII编码的字符集。

  1.3 Unicode编码

      GBxxxx系列编码确实拓展了ASCII编码而且覆盖了几乎所有的汉字,在国内用没有任何问题,但是一旦出现在网络中就会有很大的问题。因为世界上有很有拥有不同语言的国家,如果各自都是用自己的编码方式,像中国一样使用两个自己对自己的文字进行编码,那么就会出现严重的编码不兼容问题,大家互相访问就会出现乱码。

       为了解决这个问题出现了------Unicode。简单来说Unicode采用4个字节进行编码,同时兼容之前的ASCII编码。当然这又是有很大缺点的,如何任何字符都用4个字节去编码,会导致浪费大量的计算机资源,非常低效。如‘A’用一个字节01000001编码即可,但是用4个字节编码,就会在01000001前面再加上24个零,造成空间的浪费。为了解决这种空间上的浪费就出现了UTF-16,UTF-8编码。

UTF-16,UTF-8分别为16位和8位变长编码,对于UTF-16,它将0–65535范围内的字符编码成2个字节,如果真的需要表达那些很少使用的"星芒层(astral plane)"内超过这65535范围的Unicode字符,则需要使用额外的来实现。对于UTF-8,它使用使用一至四个字节为每个字符编码(不展开说了,以后补充)。

文中程序就是使用UTF-8来进行编码的,这同时又引出了一个问题,可变长编码计算机如何识别不等长编码。像程序中的“慕A”,汉字“慕”采用3个字节进行编码,而“A”采用一个字节进行编码,计算机如何区别进行解码呢?

简单来说:“慕”采用3个字节进行编码,每个自己首位都是1,而“A”符合ASCII编码即7位表示,首位是0.这也是为什么程序中不加上“&0xff”就会显示32位,因为汉字编码每个字节首位都是1,因为byte采用补码表示,所以汉字的编码转为byte类型均为负数,而负数传入toBinaryString()方法返回的就是补码字符串。














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值