Java.字符编码

字符编码
计算机里只有数字,计算机软件里的一切都是用数字来表示的,屏幕上显示的是一个个字符也不例外。

最初每一个字符都用一个数字来表示,一个字节所能表示的数字范围有256个,足以容纳所有的字符
字符a对应数字97,字符b对应数字98等,这种字符与数字对应的编码规则也被称为ASCII(American Standard Code for Information Interchange美国标准信息交换码)。ASCII的最高bit位都为0,也就是说这些数字都在0到127之间。256=2^8+(2^7+……2^1)+1

中国大陆将每一个中文字符都用两个字节的数字来表示,中文字符的每个字节的最高位bit都为1,中国大陆为每个中文字符指定的编码规则称为GB2312(国标码)

在GB2312的基础上,对更多的中文字符(包括繁体)进行了编码,新的编码规则称为GBK(可见国标2312是GBK的子集)

在中国大陆使用的计算机系统上,GBK和GB2312就被称为该系统的本地字符集

“中国”的“中”字,在中国大陆的编码是十六进制的D6D0,而在中国台湾是十六进制的A4A4,台湾地区对中文字符集的编码规则称为BIG5(大五码)。同一个字符,在不同的地区的本地字符集中对应的数字是不同的。

在一个国家的本地化系统中出现的一个字符,通过电子邮件传送到另一个国家的本地化系统中,看到的就不是那个原始字符了,而是另外那个国家的一个字符或者乱码。所以就需要一个国际通用的字符编码来拯救世界。所以Unicode编码诞生了

 

Unicode(Universal Character Set)编码就是一种全球通用的字符编码
ISO(国际标准化组织)将全世界所有的符号进行了统一编码,称之为Unicode编码
字符不在区分国家和地区
“中”这个符号,在全世界的任何角落始终对应的都是一个十六进制的数字4e2d

如果所有的计算机系统都是用Unicode编码,在中国大陆的本地化系统中显示的“中”这个符号,发送到伊拉克的本地化系统中,显示的仍然是“中”这个符号

Unicode编码的字符都占用两个字节的大小,对于ASCII码所表示的字符,只是简单地在ASCII码原来占用的一个字节前面,增加一个所有bits为0的字节。

Unicode只占用两个字节,在全世界范围内所表示的字符个数不会超过2^16(65536),实际上,Unicode编码中还保留了两千多个数值没有用于字符编码。所以中国的藏文,满文等少数民族的文字和古字等没有Unicode编码。

为了兼容以前的文档,本地化字符编码(如GB2312)将与Unicode编码共存。

java中的字符使用的都是Unicode编码,但是java在通过Unicode保证跨平台特性的前提下,也支持本地平台字符集。

 


在java语言乃至其他的编程语言特别是XML程序的开发中还会涉及到UTF-8,UTF-16等编码,尤其是UTF-8编码的应用更是广泛。
UTF是(Unicode Text Format)(UCS / Unicode Transformation Format)(不知道哪个是对的-_-!)通用字符编码的缩写。
UTF-8是将不同范围内的字符用不同个数的字节来表示的编码方式,原来ASCII码字符保持原样,仍然占用一个字节,对于其他国家的字符,UTF-8使用两个或三个字节来表示。使用UTF-8编码的文件,通常要用EF BB BF作为文件开通的三个字节数据

字符UTF-8编码与Unicode编码之间的转换关系对应一下规则:

Unicode编码在 /u0001-/u007f之间的字符,UTF-8编码为:(byte)c只占用一个字节

Unicode编码在 /u0000和范围在/u0080-/u07ff之间的字符,UTF-8编码占用两个字节。编码为:(byte)(0xc0|(0x1f&(c>>6))) , (byte)(0x80|(0x3f&c))

Unicode编码在/u0800和/uffff之间的字符,UTF-8编码为:(byte)(0xe0|(0x0f&(c>>12))) , (byte)(0x80|(0x3f&(c>>6))) , (byte)(0x80|(0x3f&c))

UTF-8的优点:
Unicode编码中对于ASCII码范围内的字符都要增加一个内容为0x00的字节,而0x00这个字节的
数据在C语言等编程语言中有特殊的作用,Unicode编码在这些应用中会产生许多冲突和麻烦。
不出现内容为0x00的字节
便于应用程序检查数据在传输过程中是否发生了错误。
直接处理使用ASCII码的英文文档。

UTF-8的缺点:
有些字符需要三个字节。

EF BB BF只是标记,表示文本使用UTF-8编码

UTF-16
UTF-16编码在Unicode基础上进行了一些细节上的扩充,增加了对Unicode编码没有包括的那些字符的表示方式。
UTF-16对Unicode的扩充并没有影响Unicode编码所包括的那些字符,只是增加了Unicode编码没有包括的那些字符的表示方式,一个使用Unicode编码的字符就是UTF-16格式的。
Unicode编码将0xD800-0xDFFF区间的数值保留出来,UTF-16扩充的字符,占用四个字节,前面两个字节的数值为0xDC00-0xDFFF之间,后面两个字节的数值为0xDC00-0xDFFF之间。
 
位运算还是搞不清楚!

在不同体系结构的计算机系统中UTF-16编码的Unicode字符在内存中的字节存储顺序是不同的。

对于0x1234这样一个双字节数据,使用Little-Endian和Big-Endian两种方式在内存中存储的

如果文件以0xFE 0xFF这两个字节开头,则表明文本的其余部分是Big-Endian的UTF-16编码;如果文件以0xFF 0xFE这两个字节开头,则表明文本的其余部分是Little-Endian的UTF-16编码。

 

public class CharCode { public static void main(String[] args) throws Exception { // TODO: Add your code here //获取本地字符集的名称 System.getProperties().list(System.out); //System.getProperties()获取虚拟机环境变量。list方法列出所有虚拟机环境变量 //更改默认本地字符集 System.setProperty("file.encoding","iso8859-1"); System.getProperties().list(System.out); //System.getProperties()获取虚拟机环境变量。list方法列出所有虚拟机环境变量 String strChina="中国"; //打印出字符串中所有字符的Unicode编码 System.out.println("打印出字符串中所有字符的Unicode编码"); for(int i=0;i<strChina.length();i++){ System.out.println(Integer.toHexString((int)strChina.charAt(i))); //取出字符串中的每一个字符,强制转换成整数,就是字符的Unicode码。String.charAt(i)取出字符串中下标为i的字符。Integer.toHexString(int)将十进制转换成十六进制 } //得到字符串中字符的GB2312编码 byte [] buf=strChina.getBytes("gb2312"); //String.getBytes()并不是简单的将字符串当中的每个字节数据简单的存放到字节数组中,而是将每个字符的Unicode编码转换成某个指定的字符集的编码然后将这些编码值存储到字节数组返回。将Unicode码转变成某种字符集编码的过程叫编码 System.out.println("得到字符串中字符的GB2312编码"); for(int i=0;i<buf.length;i++){ System.out.println(Integer.toHexString(buf[i])); } //将字节数组中的每一个字节的数据直接写入到显示器输出流中 System.out.println("将字节数组中的每一个字节的数据直接写入到显示器输出流中"); for(int i=0;i<buf.length;i++){ System.out.write(buf[i]); //显示结果为 中国 } System.out.println(); //println()会自动调用flush()方法 } } //要在屏幕上打印中文字符,写入到屏幕输出流中的那个字节的内容必须是中文字符的国标2312码

 

public class CharDecode { public static void main(String[] args) throws Exception { // TODO: Add your code here //System.getProperties().put("file.encoding","iso8859-1"); //这里有点小问题。默认字符集更改后,为什么对下面的输出没有什么影响呢?? //System.setProperty("file.encoding","iso8859-1"); System.out.println("Please enter a chinese String:"); int pos=0; byte [] buf=new byte[1024]; int ch=0; while(true){ ch=System.in.read(); System.out.println(Integer.toHexString(ch)); switch (ch){ case '/r': break; case '/n': String strInfo=new String(buf,0,pos,"iso8859-1"); for(int i=0;i<strInfo.length();i++){ System.out.println(Integer.toHexString((int)strInfo.charAt(i))); } System.out.println(new String(strInfo.getBytes("iso8859-1"),"gb2312")); pos=0; break; default: buf[pos++]=(byte)ch; } } } }

你可能感兴趣的:(exception,虚拟机,String,语言,byte,transformation)