平时总是遇到编码问题,遇到就百度,一直不理解,现在找个时间做了下笔记,方便自己理解
1. 为什么需要编码?
我们知道计算机只能存储0和1(即高低电位传递、灯明灭),所有存储在计算机里的信息都会变成 "010010101" 这样看不懂的数字,那么问题来了,如何把 "010010101" 这样的数字转变成我们能看懂的符号?
思路是这样的:
大家约定一套规则,就像小时候玩的传纸条 情报游戏,我们规定用"0001"代表"点"字,用"0003"表示“快”字,用"0020"代表"赞",这样写在纸上 0003 0001 0020 就表示"快点赞"。以此类推,计算机也是这样来表示我们能看懂的符号
所以,编码是把我们看不懂的 0101001 转变成 我们能看懂的符号,此处的编码是广义上的。
而狭义上的编码是指把我们能看懂的符号变成0101的过程,解码就是把看不懂的0101变成能看懂的符号的过程
2. 常见的编码
ASCII
因为计算机先在美国出现,而且也没有考虑到会在全世界推广,所以当时制定了一套表示美国字符的编码规则——ASCII ASCII用一个字节(byte)即8位(bit)来表示符号,这样能有28=256种符号,美国的符号其实用不了那么多,ASCII规定用低7位来表示字符,27=128种,高位用0补充,这样字母,数字,制表符等都能表示了
ISO-8859-1
由于计算机的推广,ASCII不能满足西欧,希腊等国家的符号,所以在ASCII的基础上扩展出了ISO-8859-1,也同样使用单字节表示符号,不同在于高位也利用起来了,即能表示256种符号,这样西欧国家的符号也能表示了
Unicode
随着计算机的广泛使用,ISO组织为了让全世界的符号都在计算机表示,其提出一个新的编码方式(广义)——Unicode。注意:这只是一个符号集,只规定了符号的二进制(即0101这样的)表示,没有规定怎么把这些二进制存储起来
UTF-8
UTF-8是使用最广的一种 Unicode 的实现存储方式,用变长的字节来表示符号,根据Unicode的编号大小,编号小的就用一个字节,编号大的用4个字节,从1-4字不等
UTF-16
Java 以 UTF-16作为内存的字符存储格式,其用16位即两个字节表示 Unicode 的转化格式,是定长的
总结Unicode
Unicode内有世界全部符号对应的二进制表示(很大很大),而这些二进制怎么存进计算机就是UTF-XX的规定了。这些UTF存储的只是转化的格式,用这个格式去Unicode表里按格式查找就能找出对应的字符
简单理解:Unicode是一个存储了各种符号的二维数组,而UTF-XX存储的是该二维数组的下标,那么用这些下标就可从数组中找出对应的符号了
URL编码
URL只能用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号。对于特殊的字符则被编码为ASCII十六进制字符,前后用%来标识,空格就被编码为’ ’,这样来用规定字符来表示特殊字符
3. 计算机编码
计算机的基本存储单元是字节,所以进行信息传输的也是二进制字节。那么计算机就无法直接传输字符,就需要将字符解析成二进制字节,这个解析操作就叫做编码(encode)。而相应的,将编码的二进制字节还原成字符的操作就叫做解码(decode)
4. Java的编码
java存储时所用的是UTF-8可变的方式、而JVM内存运行时所用的是UTF-16,因为UTF-16是定长的,不用像UTF-8那样再次转换计算,使用方便。
JVM内存运行时(UTF-16),所以char占两个字节。注意:String虽然是char组成,但用了更加灵活的方式存储,英文占一个字符,中文占两个字符,即英文一个字节,中文两个字节,主要提高存储效率,节省空间。这里的话String和char比就不同了
那么一个char占两个字节在utf-16情况下可以存全部的中文了。而在utf-8存储中少部分汉字不能,因为占了3-4字节