何为字符编码(名词):计算机中的任何信息它们都以0和1的方式存入计算机并得以处理,这些信息用哪些二进制数字来表示了,就需要一套规则,这套规则就是字符编码(Character Code),比如,同样一个字母'A',每种规范里面的表达存储方式不一样,ASCII是001,GB2312是002,没以下都是它的规则,如:ASCII编码表、GB2312编码表、GBK编码(即“国G标B”、“扩K展”前三个汉字的汉语拼音的第一个字母)、GB18030、Unicode编码、UTF-8编码等等(理解为一个国家或一个地区的语言包)
为什么需要知道字符编码:
在显示器上看见的文字、图片等信息在电脑里面其实并不是我们看见的样子,即使 你知道所有信息都存储在硬盘里,把它拆开也看不见里面有任何东西,只有些盘片。假设,你用显微镜把盘片放大,会看见盘片表面凹凸不平,凸起的地方被磁化,凹的地方是没有被磁化;凸起的地方代表数字1,凹的地方代表数字0。 硬盘只能用0和1来表示所有文字、图片等信息。那么字母”A”在硬盘上是如何存储的呢?可能小张计算机存储字母”A”是1100001,而小王存储字母”A”是11000010,这样双方交换信息时就会误解。比如小张把1100001发送给小王,小王并不认为1100001是字母”A”,可能认为这是 字母”X”,于是小王在用记事本访问存储在硬盘上的1100001时,在屏幕上 显示的就是字母”X”。也就是说,小张和小王使用了不同的编码表。小张用的编码表是ASCII,ASCII编码表把26个字母都一一的对应到2进制1和0 上;小王用的编码表可能是EBCDIC,只不过EBCDIC编码与ASCII编码中的字母和01的对应关系不同。一般地说,开放的操作系统(LINUX 、WINDOWS等)采用ASCII 编码,而大型主机系统(MVS 、OS/390等)采用EBCDIC 编码。在发送数据给对方前,需要事先告知对方自己所使用的编码,或者通过转码,使不同编码方案的两个系统可沟通自如。(其实发过来的都是0101010。。。,对方告知所使用的编码规范(假如是ASCII编码),就使用ASCII编码表找到对应所表达的字符,再将字符通过EBCDIC编码表找到对应的编码,然后才能得到本机正常情况下的字符)
这就解释了乱码的原因:010101在你那里代表正常的字符,你那边编码规范是ASCII编码,到我这边来编码规范是GB2312,编码表变了,010101代表什么西方字符或者问号等等,于是乱码文件就产生了
解码:你用文件编辑软件打开某个文件,假设里面装的010101,比如以UTF-8打开,就以UTF-8的语言包去解码010101,它代表刘德华,比如以GBK解码的语言包去解码010101,它代表梁朝伟
编码:名词即语言包,动词的话,就是UTF-8用010101编码(表示)刘德华,GBK以101010编码(表示)刘德华
转码:比如你之前使用GBK(2、3、4)打开的,现在我需要用UTF-8(5、6、7)打开
public static void convertionString() throws UnsupportedEncodingException{ String s = "任何信息"; //计算机上的任何信息是以010101存在的 1 byte[] b = s.getBytes("gbk");//得到文件以GBK编码表存在的方式(字节) 2 String sa = new String(b, "gbk");//用GBK编码表去解码字节代表什么 3 System.out.println(sa + b.length + "\n"); //GBK编码下的结果 4 b = sa.getBytes("utf-8");得到文件以utf-8编码表存在的方式(字节) 5 sa = new String(b, "utf-8");//用utf-8编码表去解码字节代表什么 6 System.err.println(sa + b.length); //utf-8编码下的结果 7 }
字符编码的发展
第一阶段:ASCII阶段,(American Standard Code for Information Interchange, "美国信息交换标准码")
计算机当时只支持英语,字符在计算机中都是以0和1的方式存储的。象a、b、c、d这样的52个字母(包括大写)、以及0、1、 2等数字还有一些常用的符号(例如*、#、@等)在计算机中存储时也要使用二进制数来表示,而具体用哪些二进制数字表示哪个符号,就必须要有一定的规则, 于是美国有关的标准化组织就出台了所谓的ASCII编码,统一规定了上述常用符号用哪个二进制数来表示。ASCII码规定每个字符例如 “a”使用1个字节来表示,也就是8位的二进制组合,那么就有00000000-11111111一共256种组合,也就是可以表示256个不同的字符。
其中0-31:是控制字符或通讯专用字符(不可以显示的字符,其余为可显示字符),如控制符:LF(换行)、CR(回车)等。
32-126:是字符,其中32是空格,48-57为0-9的阿拉伯数字,65-90为26个大写英文字母,97-122为26个小写英文字母,其余的是一些标点符号,运算符号等。
ASSCII共计有128个,从0到127,也就是从00000000-01111111,最高位都是0。
ISO 8859-1它以ASCII为基础,在空置的0xA0-0xFF的范围内,加入96个字母及符号,藉以供使用变音符号的拉丁字母语言使用。
第二阶段:ANSI编码阶段(American National Standards Institute,美国国家标准学会的标准码)
ASCII只能表示英文字符,那么其他字符怎么表示呢?汉语是这样解决的,用两个ASCII表示一个汉字, 而且不用前面的128个,为什么不用已经在上一篇中介绍了,因为前128个是人家的英文。不能占啊,否则就混乱了。比如汉字“中”在中文操作系统中使用 [0xD6,0xD0] 这两个字节存储,为什么呢,这里简单解释一下,“中”的区位码是 54 48 ,那么“中”的,国标码就是54 48的十六进制+上2020H=5650H,那么“中”的机内码就是=“中的国标码+8080H=D6D0H(这都是上一篇的内容,不明白的可以看上一 篇),这样每个汉字也都有了自己的编码,汉字编码解决了,这就是中国的GB2312编码标准,但是这是中国汉字的编码,那么其他国家呢?其他的国家的计算 机操作系统中可能把[0xD6,0xD0] 这两个字节存储成他们的文字,而不是“中”,不同的国家和地区制定了不同的标准,这些使用 2 个字节来代表一个字符的各种文字延伸编码方式,称为 ANSI 编码。
在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。
第三阶段:Unicode(16进制) 字符集编码阶段(Universal Multiple-Octet Coded Character Set, 通用多八位编码字符集的简称)
为了使国际间信息交流更加方便,国际组织制定了 UNICODE(16进制) 字符集, 为各种语言中的每一个字符设定了统一并且唯一的数字编号,以满足跨语言、跨平台进行文本转换、处理的要求。Unicode固然统一了编码方式,但是它的效率不高,比如UCS-4(Unicode的标准之一)规定用4个字节存储一个符号,那么每个英文字母前都必然有三个字节是0,这对存储和传输来说都很耗资源。
UCS只是规定如何编码,并没有规定如何传输、保存这个编码。
UTF-8:utf(Unicode Translation Format)为了提高Unicode的编码效率,于是就出现了UTF-8编码。Unicode规定世界上每个字符对应的编码号,utf-8定义了如何存储字符,UTF-8使用可变长度字节来储存 Unicode字符,例如ASCII字母继续使用1字节储存,重音文字、希腊字母或西里尔字母等使用2字节来储存,而常用的汉字就要使用3字节。辅助平面字符则使用4字节。
UTF-16、UTF-32 都是将数字转换到程序数据的编码方案。
java在内存中运算是使用的双字节字符unicode的编码方式
内存中对字符串操作其实不用考虑字符集。
只有在读取到内存中,和输出时,需要考虑字符集转换。
http://www.blogjava.net/liuyz2006/articles/385768.html