各种字符编码的知识-ASCII,Unicode,UTF-8,UTF-16

    xiaoxiao2025-02-28  21

    硬盘是用来存储数据信息的,它的表面凹凸不平,凸起的地方被磁化,凹的地方是没有被磁化;凸起的地方代表数字1,凹的地方代表数字0。硬盘只能用01来表示所有文字、图片等信息。

    一.字符编码

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

    b) 字符a对应数字97,字符b对应数字98等,这种字符与数字对应的编码规则被称为ASCII(美国标准信息交换码)。ASCII的最高bit位都为0,也就是说这些数字都在0127之间。

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

    d) 在GB2312的基础上,对更多的中文字符(包括繁体)进行了编码,新的编码规则称为GBK

    e) 在中国大陆使用的计算机系统上,GBKGB2312就被称为该系统的本地字符集。

    f) 台湾地区对中文字符集的编码规则称为BIG5(大五码)。

    g) 在一个国家的本地化系统中出现的一个字符,通过电子邮件传送到另一个国家的本地化系统中,看到的就不是那个原始字符了,而是另外那个国家的一个字符或乱码。

    二.ASCIIEBCDIC

    a) ASCII码使用72进制数表示一个字符,这样,72进制数可以表示出27次方个字符,共128个字符。EBCDIC码使用8位,可以表示出28次方个字符,256个字符。

    b) 虽然标准 ASCII 码是 位编码,但由于计算机基本处理单位为字节( 1byte = 8bit ),所以一般仍以一个字节来存放一个 ASCII 字符。每一个字节中多余出来的一位(最高位)在计算机内部通常保持为 (在数据传输时可用作奇偶校验位)。 

    三.Unicode编码

    a) ISO(国际标准化组织)将全世界所有的符号进行了统一编码,称之为Unicode编码。

    b) “中”这个符号,在全世界任何角落始终对应的都是一个16进制的数字4e2d

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

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

    e) Unicode只占用两个字节,在全世界范围内所表示的字符个数不会超过216次方(65536),实际上,Unicode编码中还保留了两千多个数值没有用于字符编码。

    f) 在相当长的一段时期内,本地化字符编码将于Unicode编码共存。

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

    四.UTF-8编码 

    a) ASCII码字符保持原样,仍然只占用一个字节,对于其他国家的字符,UTF-8使用两个或三个字节来表示。使用UTF-8编码的文件,通常都要用EF BB BF作为文件开头的三个字节数据。

    b) 优点:

    i. 不出现0x00字节。

    ii. 便于应用程序检测数据在传输过程中是否发生了错误。

    iii. 直接处理使用ASCII码的英文文档。

    c) 缺点:

    i. 某些字符是用三个字节来表示。

    五.UTF-16编码

    a) UTF-16编码在Unicode基础上进行了一些细节上的扩充,增加了对Unicode编码没有包括的那些字符的表示形式。

    b) UTF-16Unicode编码的扩充并没有影响到Unicode编码所包括的那些字符,只是增加了对Unicode编码没有包括的那些字符的表示形式,一个使用Unicode编码的字符就是UTF-16格式的。

    c) Unicode编码将0xD800-0xDFFF区间的数值保留出来。UTF-16扩充的字符就是利用这2048个数字进行的。扩展的字符占四个字节,前面两个字节的数值为0xD800-0xD8FF之间,后面两个字节的数值在0xDC00-0xDFFF之间。

    d) 为什么不让前面和后面的两个字节的数值都为于0xD800-0xDFFF之间呢?

    i. 容易分清字符界限,检测数据传输。

    ii. 扩展的二百多万的字符已经够用。

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

    i. 对于0x1234这样的一个双字节数据,使用Little-EndianBig-Endian两种方式在内存中存储的格式如图所示:

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

    六.字符编码的操作体验

    package CharCode;

    import java.io.File;

    public class CharCodeTest {  public static void main(String[] args) throws Exception {   //修改系统所使用的缺省字符集   System.setProperty("file.encoding", "iso8859-1"); //???????????????我的程序好像没有改变使用平台默认的字符集   System.setProperty("sun.jnu.encoding", "iso8859-1");   //获得jvm的环境属性System.getProperties   System.getProperties().list(System.out);   //jvm的file.encoding=gbk是jvm的缺省字符集

      String str="中国";   for(int i=0;i<str.length();i++){    System.out.println(Integer.toHexString((int)str.charAt(i)));//toHexString是将数字转化成16进制   }   //byte []buf = str.getBytes("gb2312");   //将Unicode字符转换为指定的“gb2312”字符集的编码格式,称为编码||jdk中一定要存在编码器类   byte []buf = str.getBytes(); // 使用平台默认的字符集将此 String 解码为字节序列,并将结果存储到一个新的字节数组中。   for(int i=0;i<buf.length;i++){    System.out.println(Integer.toHexString(buf[i]));      }   for (int i = 0; i < buf.length; i++) {    System.out.write(buf[i]); //write方法输出字节,没有调用flush方法,不会自动刷新缓冲区   }   System.out.println();//刷新缓冲区   //System.out.write(buf,0,6); //字节数组,调用了flush会刷新缓冲区,会自动刷新缓冲区   System.out.println("中国");  //按照本地字符集解码   //PrintStream.println();System.out是PrintStream的实例对象。先转化后打印(getByte,write)它的实现是  } }

     

    七.字符编码的编程体验

    package CharCode;

    import java.io.UnsupportedEncodingException; import java.nio.Buffer;

    public class CharDeCode {

     /**   * @param args   * @throws UnsupportedEncodingException    */  public static void main(String[] args) throws Exception {   //System.getProperties().setProperty("fileEncoding", "iso8859-1");//不起作用啊?????????   System.out.println("请输入字符串:");   byte [] buf=new byte[1024];   int pos=0;   int ch;   String strInfo="";   int s=0;   while(s!=1){    ch =System.in.read();//System.in.read()返回的是输入数值的 ASKII 码(一个 int 整数)。    System.out.println(Integer.toHexString(ch));//打印输入的码值    switch (ch) {    case '\r'://回车     break;    case '\n':     strInfo=new String(buf,0,pos);     s=1;     break;    default:     buf[pos++]=(byte)ch;     break;    }   }   for (int i = 0; i < strInfo.length(); i++) {    //System.out.println(buf[i]);    System.out.println(i+"\t"+Integer.toHexString(strInfo.charAt(i)));   }   System.out.println(strInfo);  }  

    }

    a) 字节是用于表示计算机内存中的最原始的数据,不涉及编码的问题。当把字节里的内容当字符处理的时候,才会涉及到字符编码问题。

    b) 所以与字符处理的IO流,他们都有一个接收字符集的参数来指定所用的字符集。

    转载自:http://blog.csdn.net/wangfayinn/article/details/6755140

    顶 0 踩
    转载请注明原文地址: https://ju.6miu.com/read-1296729.html
    最新回复(0)