计算机中的编码问题

计算机中的编码问题

因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),如果要表示更大的整数,就必须用更多的字节。比如两个字节可以表示的最大整数是65535,4个字节可以表示的最大整数是4294967295。

一、目前常用的编码

ASCII编码:由于计算机是美国人发明的,因此,最早只有127个字母被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。
GB系列编码:但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。进而全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。GB系列编码是我国的国标编码,用来存储汉字,分为GB2312,GBK,GB18030,基本都能向前兼容,其中GBK是目前最通用的。

Unicode编码:Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。不过他只规定了字符的编码,却没有规定字符以何种方式存储或者传输。所以UTF系列编码规定了Unicode编码的存储和传输方式。

UTF编码系列:目前最常用的UTF编码分为3种,UTF-8,UTF-16和UTF-32,我们知道计算机是以8位为一个字节来存储数据的,而UTF-16,UTF-32分别用2字节和4字节来表示一个字符,所以这里就涉及到字节的存储顺序,是低位在前还是高位在前,这样,BOM就产生了。

BOM是文本文件开头的一个特殊标记,用一组特殊数字来标记文本文件的字节序。虽然UTF-8字节顺序是固定的,但为了兼容UTF-16和UTF-32也规定了UTF-8的BOM,用于标记UTF-8编码。不过UTF-8的BOM在不同平台的规定不同,要小心使用。BOM规定如下:

UTF-8 EF BB BF

UTF-16(LE) FF FE

UTF-16(BE) FE FF

UTF-32(LE) FF FE 00 00

UTF-32(BE) 00 00 FE FF

UTF-8编码:如果统一成Unicode编码,乱码问题从此消失了。但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就十分不划算。所以,本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:

字符 ASCII Unicode UTF-8
A 01000001 00000000 01000001 01000001
X 01001110 00101101 11100100 10111000 10101101

二、计算机系统中的编码应用

在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码;用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件:

浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器:

所以你看到很多网页的源码上会有类似<meta charset="UTF-8" />的信息,表示该网页正是用的UTF-8编码。

三、Java中的编码问题

直接写一个demo来看看eclipse中java项目的编码是怎么样的吧。

1、字符串转为字节序列

 1 public class EncodeDemo {
 2
 3     public static void main(String[] args) {
 4         // TODO Auto-generated method stub
 5         String s="云开de立夏";
 6         byte[] bytes1=s.getBytes();//这是把字符串转换成字符数组,转换成的字节序列用的是项目默认的编码
 7         for(byte b: bytes1)
 8         //toHexString这个函数是把字节(转换成了Int)以16进制的方式显示
 9         System.out.print(Integer.toHexString(b & 0xff)+" ");// & 0xff是为了把前面的24个0去掉只留下后八位
10     }
11
12 }

运行结果:

分析:可以看到这个java项目的默认编码中,汉字用2个字节表示,英文用一个字节表示。

通过查看项目的默认编码为GBK。

如果不想用项目默认的编码格式,可以用下面这种方法指定字符串转化为想要的编码格式:

1 byte[] bytes2=s.getBytes("utf-8");//转换成utf-8编码
2         for(byte b: bytes2)
3             //toHexString这个函数是把字节(转换成了Int)以16进制的方式显示
4             System.out.print(Integer.toHexString(b & 0xff)+" ");// & 0xff是为了把前面的24个0去掉只留下后八位
5         System.out.println();
6         byte[] bytes3=s.getBytes("utf-16be");//转换成java双字节编码,utf-16be编码
7         for(byte b: bytes3)
8             //toHexString这个函数是把字节(转换成了Int)以16进制的方式显示
9             System.out.print(Integer.toHexString(b & 0xff)+" ");// & 0xff是为了把前面的24个0去掉只留下后八位

运行结果:

分析:两个结果对比可以得出,

gbk编码: 中文占用两个字节,英文占用一个字节。

utf-8编码:中文占用三个字节,英文占用一个字节。

utf-16be编码:中文占用两个字节,英文占用两个字节。

注意:java是双字节编码,是utf-16be编码。即java中的一个字符(char)占用两个字节!



2、字节序列转为字符串

当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,也需要用这种编码方式,否则会出现乱码。

1 String str1=new String(bytes1);//这时会使用项目默认的编码来转换,可能出现乱码
2         System.out.println(str1);
3         String str2=new String(bytes2);
4         System.out.println(str2);
5         String str3=new String(bytes2,"utf-8");
6         System.out.println(str3);

运行结果:

四、文本文件(txt)的编码问题

文本文件就是字节序列,可以是任意编码的字节序列。

如果我们在中文机器上直接创建文本文件,那么该文件只认识ANSI编码(例如直接在电脑中右键创建文本文件)。

这里要注意:只有直接创建文本文件时,该文件的编码只认识ANSI,但是文本文件本身是可以放任意编码的字节序列。

注意:中文系统下,ANSI编码即是GBK编码。

这里举个例子:

我们在eclipse新建一个项目,把它的默认编码改为utf-8

那么对于这个项目而言,它只认识utf-8的编码文件。

接下来,我们在这个项目中新建一个文本文件utf-8.txt,并在里面输入内容如下:

   

如果直接把这个文本文件拷贝到其他项目中(默认为GBK编码),里面的内容将会变成乱码!因为编码不一样!

但是如果是将里面的内容复制粘贴过去,系统会自动转化为相应的编码,是不会出现乱码的。

注意:如果把这个文本文件拷贝到其他地方(比如系统的桌面)上,它不会出现乱码!!因为文本文件可以是任意的编码序列,系统在读取文本文件时会自动转化为相应的编码格式。



了解文件的编码有什么用呢??在Java的IO流中,我们需要对文件进行读写,使用字节流进行读写的时候,就必须根据不同的编码方式进行读写。因为不同编码方式的各个字符所占用的字节数不同,我们要按照实际情况进行操作。好了,下期预告:《Java中File类的使用》

参考博文:

http://blog.csdn.net/u012050154/article/details/50774098#t2

时间: 2024-10-17 12:35:06

计算机中的编码问题的相关文章

聊聊计算机中的编码(Unicode,GBK,ASCII,utf8,utf16,ISO8859-1等)

作为一个程序员,一个中国的程序员,想来“乱码”问题基本上都遇到过,也为之头疼过.出现乱码问题的根本原因是编码与解码使用了不同而且不兼容的“标准”,在国内一般出现在中文的编解码过程中. 我们平时常见的编码有Unicode,GBK,ASCII,utf8,utf16,ISO8859-1等,弄清这些编码之间的关系,就不难理解“乱码”出现的原因以及解决办法. 所谓字符集编码其实就是将字符(包括英文字符.特殊符号,控制字符,数字,汉子等)与计算机中的一个数字(二进制存储)一一对应起来,用这个数字来表示该字符

计算机中的进制和编码(转载)

原文出处: http://www.cnblogs.com/resn/p/5775378.html 古时候,人们是如何来传递消息的? 当年周幽王为博褒妃一笑,不顾众臣反对,竟数次无故点燃边关告急用的烽火台,使各路诸侯,长途跋涉,匆忙赶去救驾.结果,被戏而回.周幽王从此便失信于诸侯,最后,当边关真的告急之时,他点燃烽火却再也没人赶来救他了!不久,便死于刀下,亡了西周.西周第九代国君是周厉王,贪财好色,昏庸残暴,激起了公元前841年的"国人(平民)暴动".周朝从此衰落下去,社会动荡不安. 扯

计算机中的进制和编码

计算机中的进制和编码 古时候,人们是如何来传递消息的? 当年周幽王为博褒妃一笑,不顾众臣反对,竟数次无故点燃边关告急用的烽火台,使各路诸侯,长途跋涉,匆忙赶去救驾.结果,被戏而回.周幽王从此便失信于诸侯,最后,当边关真的告急之时,他点燃烽火却再也没人赶来救他了!不久,便死于刀下,亡了西周.西周第九代国君是周厉王,贪财好色,昏庸残暴,激起了公元前841年的"国人(平民)暴动".周朝从此衰落下去,社会动荡不安. 扯远了,我们说有城池A和城池B,城池B为前线,当城池B受到攻击的时候,需要城池

网络编程中的编码问题汇总

应用程序中的编码问题让人头疼,一直是这样,今天下午就被数据库编码错误搞的头疼不已. 那么,就决心好好总结一下编码带来的问题,争取让自己对整个编码体系有一个清晰的认识. 从编码问题的产生说起 我们知道,计算机是美国人发明的,人家的英语体系总从来就只有26个英文字母和一些数字.特殊字符等,为了储存文字信息,于是使用了最早的ascii码进行字符编码.而后来由于计算机的普及,多国语言文字变得重要起来,于是多语言的特性成为了计算机的必备,各国进行各国的国家标准编码,中国的便是GB2312(1980年),而

http协议中的编码和解码

http://www.csdn1 2 3.com/html/itweb/20130730/29422_29378_29408.htm ****************************** 一.字符集与文字编码简介 1. 计算机如何显示文字 我们知道,计算机是以二进制的“形式”来保存和处理数据的,也 就是说,不管我们使用键盘进行输入,还是让计算机去读取一个文本文件,计算机得到的原始内容是一些二进制序列,当需要对这些二进制序列进行显示时,计算机 会依照某种“翻译机制”(也就是编码方式),取到

python语言中的编码问题

在编程的过程当中,常常会遇到莫名其妙的乱码问题.很多人选择出了问题直接在网上找答案,把别人的例子照搬过来,这是快速解决问题的一个好办法.然而,作为一个严谨求实的开发者,如果不从源头上彻底理解乱码产生的机制,并由此寻求解决问题的根本路径,那么永远不能从码农的阴影中摆脱出来.下面就来一起了解一下计算机编码问题的来龙去脉. ASCII 众所周知,计算机中的所有数据,不论是文字.图片.视频.还是音频文件,本质上最终都是按照类似 01010101 的二进制形式存储的.然而,计算机中的字符,并不能完全以这种

计算机中的浮点数(IEEE754)

IEEE读作[a?-'tr?p(?)l-i:],电气和电子工程师协会.这个是一个包括所有电子和计算机技术的专业团体,制定标准是其工作之一. IEEE浮点数算术标准(IEEE 754)是最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用. 整数运算和浮点数运算会有不同的数学属性是因为它们处理数字表示有限性的方式不同——整数的表示算然只能编码一个相对较小的数字范围,但是这种表示是精确的:而浮点数虽然可以编码一个较大的数值范围,但是这种表示只是近似的. IEEE规定的浮点数编码会将一个浮点数转

计算机中的整数(原码、反码、补码)

系统中所有的信息——包括磁盘文件.存储器中的程序存储器中存放的用户数据以及网上落上传送的数据,都是由一串位表示的.区分不同数据对象的唯一方法是我们读到这些数据对象时的上下文.比如,在不同的上下文中,一个同样的字节序列可能表示一个整数.浮点数.字符串或者机器指令. 计算机中的整数可以分为无符号整数和有符号整数两种类型.无符号整数不存在正负之分,在计算机中以其二进制真值的形式存放.而有符号整数由于有正负数的区分,表示相对复杂. 计算机中的符号数有三种表示方法,即原码.反码和补码.三种表示方法均有符号

深入分析Java Web中的编码问题

编码问题一直困扰着我,每次遇到乱码或者编码问题,网上一查,问题解决了,但是实际的原理并没有搞懂,每次遇到,都是什么头疼. 决定彻彻底底的一次性解决编码问题. 1.为什么要编码 计算机的基本单元是字节,一个字节是8bit.一个字节的范围是0~255. 人类要表示的符号肯定比256个多,所以无法用一个字节来表示这个多的符号. 你想想,光汉字就有几千个. 要解决这个矛盾,有了一个新的数据结构:char.char也就是字符,最长16bit,最短为8bit.一个字符的最大长度是16bit.一个字符的范围是