编码和解码可以理解成二进制和字符(广义的字符,包括汉字等)的映射表,编码即从字符映射至二进制,解码则为逆过程。

1.英语字符编码ASCII

开始计算机只在美国用。8字节一共可以组合出256(2的8次方)种不同的状态。美国人把其中的编号从0开始的32种状态分别规定了特殊的用途,一但终端、打印机遇上约定好的这些字节被传过来时,就要做一些约定的动作。遇上00x10, 终端就换行,遇上0x07, 终端就向人们嘟嘟叫,例好遇上0x1b,
打印机就打印反白的字,或者终端就用彩色显示字母。他们看到这样很好,于是就把这些0x20以下的字节状态称为"控制码"。

  他们又把所有的空格、标点符号、数字、大小写字母分别用连续的字节状态表示,一直编到了第127号,这样计算机就可以用不同字节来存储英语的文字了。大家看到这样,都感觉很好,于是大家都把这个方案叫做 ANSI 的"ASCII"编码(American Standard Code
for Information Interchange,美国信息互换标准代码)。当时世界上所有的计算机都用同样的ASCII方案来保存英文文字。

随着世界各地的都开始使用计算机,但是很多国家用的不是英文,他们的字母里有许多是ASCII里没有的,为了可以在计算机保存他们的文字,他们决定采用127号之后的空位来表示这些新的字母、符号,还加入了很多画表格时需要用下到的横线、竖线、交叉等形状,一直把序号编到了最后一个状态255。从128到255这一页的字符集被称"扩展字符集"。

简而言之,ASCII码一共规定了128个字符的编码,比如空格“SPACE”是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。

2.中文编码GB2312、GBK、GB18030

GB2312:GB2312 是对 ASCII 的中文扩展。中国人得到计算机时,已经没有可以利用的字节状态来表示汉字,况且有6000多个常用汉字需要编码。我们规定:一个小于127的字符的意义与原来相同(同ASCII),但两个大于127的字节连在一起时,就表示一个汉字,其中高字节范围规定为从0xA1—0xF7,低字节范围规定为从0xA1—0xFE。这套编码中,不仅包括了7000多个常用简体汉字,还包括数学符号、罗马希腊字母、日文假名。
ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,即所谓的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。GB2312使用两个字节表示一个汉字,所以理论上最多可以表示256x256=65536个符号。

GBK 标准:由于中国仍旧有许多偏僻字无法表示。后来规定:只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。即形成GBK标准,GBK 包括了 GB2312
的所有编码,同时又增加了近20000个新的汉字(包括繁体字)和符号。GBK标准包括拉丁字母、汉字、日文、韩文、俄文,不包括俄语、葡萄牙语。

GB18030标准:扩展至少数民族字母符号。

这一系列标准称为 "DBCS"(Double Byte Charecter Set 双字节字符集)。其最大的特点是2字节长的汉字字符和1字节长的英文字符并存于同一套编码方案里。以前的程序程序为了支持中文处理,必须要注意字串里的每一个字节的值,如果这个值是大于127的,那么就认为一个双字节字符集里的字符出现了。注意,GB类的汉字编码与后文的Unicode和UTF-8是毫无关系。

3.统一码UNICODE

    各个国家都像中国这样搞出一套自己的编码标准,结果互相之间谁也不懂谁的编码,谁也不支持别人的编码。即,尽管二进制相同,由于映射表不一样,换成他人的标准解出来就是乱码。虽然英语用128个符号编码就够了,但是用来表示其他语言,128个符号是不够的。比如,在法语中,字母上方有注音符号,它就无法用ASCII码表示。于是,一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比如,法语中的é的编码为130(二进制10000010)。这样一来,这些欧洲国家使用的编码体系,可以表示最多256个符号。但是,这里又出现了新的问题。不同的国家有不同的字母,因此,哪怕它们都使用256个符号的编码方式,代表的字母却不一样。比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel
(ג),在俄语编码中又会代表另一个符号。

ISO 解决了这个问题。他们采用的方法很简单:废了所有的地区性编码方案,重新搞一个包括了地球上所有文化、所有字母和符号的编码!这种它"Universal Multiple-Octet Coded Character Set",简称 UCS, 俗称
"UNICODE"。

    UNICODE 开始制订时,计算机的存储器容量极大地发展了,空间再也不成为问题了。于是 ISO 就直接规定必须用两个字节,也就是16位来统一表示所有的字符。对于ASCII里的那些“半角”字符(1-127),UNICODE 包持其原编码不变,只是将其长度由原来的8位扩展为16位,而其他文化和语言的字符则全部重新统一编码。由于"半角"英文符号只需要用到低8位,所以其高8位永远是0。因此这种大气的方案在保存英文文本时会多浪费一倍的空间。

但是,UNICODE 在制订时没有考虑与全球任何一种现有的编码方案保持兼容,这使得 GBK 与UNICODE 在汉字的内码编排上完全是不一样的。但由于其对于所有语言的通用性,得到了迅速推广,比如MS 和WINDOWS
操作系统。

Unicode是一个很大的集合,现在的规模可以容纳100多万个符号。每个符号的编码都不一样,比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表示汉字“严”。

4.UNICODE传输标准之UTF-8

一般而言,UNICODE
用两个字节来表示为一个字符,他总共可以组合出65535不同的字符,这大概已经可以覆盖世界上所有文化的符号。如果还不够也没有关系,ISO已经准备了UCS-4方案,说简单了就是四个字节来表示一个字符,可以组合出21亿个不同的字符。

但是注意到Unicode只是一个符号集(映射表),它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。比如,汉字“严”的unicode是4E25(100111000100101)表示至少需要2个字节。这里就有两个严重的问题:

       1.如何才能区别unicode和ascii?计算机怎么知道三个字节表示1个符号而不是分别表示3个符号
        2.存储浪费。英文字母只用一个字节表示就够了,unicode可能会使用2个以上的字节表示英文字母,大量的0浪费了存储。

在互联网普及的背景下,出现了传输unicode的UTF标准(Unicode Transformation Format)。例如普遍使用的UTF-8(Unicode Transformation Format -8 bit)就是每次8个位传输数据,而UTF-16就是每次16个位。为了传输时的可靠性,从UNICODE到UTF要过一些算法和规则来转换。Unicode码转换成UTF-8传输码规则如下:

              Unicode符号范围 | UTF-8编码方式
                   (十六进制) | (二进制)
          --------------------+---------------------------------------------
          0000 0000-0000 007F | 0xxxxxxx
          0000 0080-0000 07FF | 110xxxxx 10xxxxxx
          0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
          0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

举例而言  "汉"字的Unicode编码是6C49(范围0800-FFFF,二进制0110 1100 0100 1001),使用模板:1110xxxx 10xxxxxx 10xxxxxx转成UTF-8为E6
B1 89(1110-0110 10-110001 10-001001)。同样,汉字“严”的unicode是4E25(100111000100101),对应的UTF-8编码是E4B8A5(“11100100 10111000 10100101”)。

     例子在 windows 的记事本里新建一个文件,输入"联通"两个字之后,保存,关闭,然后再次打开,你会发现这两个字已经消失了,代之的是几个乱码!

   其实这是GB2312编码与UTF8编码冲突导致的。新建一个文本文件时,记事本的编码默认是ANSI,如果你在ANSI的编码下输入汉字,那么他实际使用GB系列的汉字编码方式,在这种编码下,"联通"的二进制码是C1AA (1100
0001 1010 1010),CDA8(1100 1101 1010 1000)。注意到,“联通”的GB编码都符合UTF-8的第二种模板("110***** 10******"),再次打开记事本时,记事本就误认为这是一个UTF-8编码的文件。会将其转回统一码显示,其统一码Unicode为 006A 0368("0000
0000 0110 1010"),前者是小写的字母"j",而后者什么也不是。这就是显示为乱码的原因。而如果你在"联通"之后多输入几个字,其他的字的编码不见得又恰好是110和10开始的字节,这样再次打开时,记事本就不会坚持这是一个UTF-8编码的文件,而会用ANSI的方式解读,这时乱码又不出现了。

5.Little
endian和Big endian的区别与识别

这两个古怪的名称来自英国作家斯威夫特的《格列佛游记》。在该书中,小人国里爆发了内战,战争起因是人们争论,吃鸡蛋时究竟是从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开。为了这件事情,前后爆发了六次战争,一个皇帝送了命,另一个皇帝丢了王位。

在网络里传递信息时有一个很重要的问题,就是对于数据高低位的解读方式,一些计算机是采用低位先发送的方法,例如我们PC机采用的 INTEL 架构,而另一些是采用高位先发送的方式,如网络中交换数据。为了便于传输,采用标志符的方法。具体而言二者区别如下。

   Big-Endian俗称大头存储:内存从最低地址开始按顺序存放,低位地址存放数据高位字节。UFT 格式文本流传送标志位FEFF 
   Little-Endian俗称小头存储:内存从最低地址开始按顺序存放,低位地址存放数据低位字节。UFT格式文本流传送标志位FFFE

6.中文window操作系统编码总结

1)ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows简体中文版,如果是繁体中文版会采用Big5码)。英文字母占1个字节,汉字占2个字节

2)Unicode编码(默认的little endian)具体指UCS-2编码方式,即直接用2个字节的Unicode码。英文和汉字都是2个字节存储。

3)Unicode big endian编码与上一个选项相对应。英文和汉字都是2个字节存储。

4)UTF-8编码,也就是上一节谈到的编码方法。一个英文字母占1个字节,一个汉字占3个字节

一般而言,ANSI占用存储空间最小,也就是为什么默认使用的原因。

7.编码的相互转换

public class Tranform {
public static void main(String args[]) throws Exception {
String chineseStr="我们";
Transform t=new Transform();
System.out.println(t.Chinese2UTF_8(chineseStr));
System.out.println(t.Chinese2GBK(chineseStr));
System.out.println(t.GBK2Chinese(t.Chinese2GBK(chineseStr)));
}
} class Transform {
//中文转换成UTF-8编码(16进制字符串),每个汉字3个字节
public String Chinese2UTF_8(String chineseStr)throws Exception {
StringBuffer utf8Str = new StringBuffer();
byte[] utf8Decode = chineseStr.getBytes("utf-8");
for (byte b : utf8Decode)
utf8Str.append(Integer.toHexString(b&0xFF));
return utf8Str.toString().toUpperCase();
} //中文转换成GBK码(16进制字符串),每个汉字2个字节
public String Chinese2GBK(String chineseStr)throws Exception {
StringBuffer GBKStr = new StringBuffer();
byte[] GBKDecode = chineseStr.getBytes("gbk");
for (byte b : GBKDecode)
GBKStr.append(Integer.toHexString(b&0xFF));
return GBKStr.toString().toUpperCase();
} //16进制GBK字符串转换成中文
public String GBK2Chinese(String GBKStr)throws Exception{
byte[] b = HexString2Bytes(GBKStr);
String chineseStr = new String(b, "gbk");//输入参数为字节数组
return chineseStr;
} //把16进制字符串转换成字节数组
public byte[] HexString2Bytes(String hexStr) {
byte[] b = new byte[hexStr.length() / 2];
for (int i = 0; i < b.length; i++)
b[i]=(byte) Integer.parseInt(hexStr.substring(2*i,2*i+2),16);
return b;
} //把字节数组转换成16进制字符串
public static final String bytesToHexString(byte[] byteArray){
StringBuffer hexStr = new StringBuffer(byteArray.length*2);
for (int i = 0; i < byteArray.length; i++) {
String sTemp= Integer.toHexString(0xFF& byteArray[i]);
int j=0;
while(j<2-sTemp.length())
{sTemp="0"+sTemp;j++;}
hexStr.append(sTemp.toUpperCase());
}
return hexStr.toString();
} }

注意:

   str.getBytes("UTF-8"); 的意思是以UTF-8的编码取得字节
new String(XXX,"UTF-8"); 的意思是以UTF-8的编码生成字符串 public static String toUtf_8(String str) {
return new String(str.getBytes("UTF-8"),"UTF-8");//字符串转成utf8
}

本文参考:

1.http://blog.csdn.net/iefreer/article/details/4836844

2.http://bbs.csdn.net/topics/360164725

3.http://www.hackbase.com/tech/2009-03-16/51640_1.html

4.http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

5.各种编码UNICODE、UTF-8、ANSI、ASCII、GB2312、GBK详解

6.英语音标和Unicode

字符编码ANSI、ASCII、GB2312、GBK、GB18030、UNICODE、UTF-8小结的更多相关文章

  1. 字符编码-ASCII,GB2312,GBK,GB18030

    ASCII ASCII,GB2312,GBK,GB18030依次增加,向下兼容. 手机只需要支持GB2312 电脑中文windows只支持GBK 发展历程 如果你使用编译器是python2.0版本,默 ...

  2. 字符集、字符编码、国际化、本地化简要总结(UNICODE/UTF/ASCII/GB2312/GBK/GB18030)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明   普通的linux 和 普通的windows.    ...

  3. 编码方式ASCII、GBK、Unicode、UTF-8比较

    文章内容深度较浅,详细了解可到下链接:https://blog.csdn.net/QuinnNorris/article/details/78705723; 总结了以下几种编码方式: ASCII.GB ...

  4. AJPFX解析关于编码ansi、GB2312、unicode与utf-8的区别

    大家平时遇到乱码问题是否有自己的一套解决方案?这篇文章就是介绍一下常用的编码方式关于编码ansi.GB2312.unicode与utf-8的区别 先做一个小小的试验: 在一个文件夹里,把一个txt文本 ...

  5. 三种字符编码:ASCII、Unicode和UTF-8

    原文:三种字符编码:ASCII.Unicode和UTF-8 什么是字符编码? 计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit)作为一个字 ...

  6. 字符编码,ASCII、Unicode与UTF-8的理解

    首先我们先要明白的两点是:1.计算机中的信息都是由二进制的0和1储存的:2.我们再计算机屏幕上看到的各种字符都是计算机系统按照一定的规则将二进制数字转换而来的. 一.基本概念. 1.字符集(chars ...

  7. 汉字编码:GB2312, GBK, GB18030, Big5

    前一篇博文:ANSI是什么编码?中有这样一段小故事: 话说计算机是由美国佬搞出来的嘛,他们觉得一个字节(可以表示256个编码)表示英语世界里所有的字母.数字和常用特殊符号已经绰绰有余了(其实ASCII ...

  8. 一文读懂所有的编码方式(UTF-8、GBK、Unicode、宽字节...)

    编码方式就分两类:ANSI编码.Unicode编码.这两类编码都兼容ASC码. ------------------------------------------------------------ ...

  9. 转载:字符编码简介 ASCII UTF-8 ISO8859-1

    字符编码简介 ASCII UTF-8 ISO8859-1 博客分类: 电脑综合知识 XP数据结构Windows  计算机中的一切都是以数字来表示的,字符同样如此.字符编码就是将字符集编码成为数字序列, ...

  10. 字符编码,pyton中的encode,decode,unicode()

    1.在计算机处理的程序中,对字符的处理有两种方式:编码或译码(encoding),解码(decoding)     encoding:将字符串中的字符转换到对应编码字符集对应的代码点         ...

随机推荐

  1. 如何解决Asp.Net MVC和WebAPI的Controller名称不能相同的问题

    1.问题描述 假如有一个文章的业务(Article),我们在 Controllers文件夹中创建MVC Controller和Api Controller,各个Controller中都有相同的获取文章 ...

  2. HTML 5 本地存储

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...

  3. mysql sql语句:行转列问题

    存在表score,记录学生的考试成绩,如下图所示: 现要求以 学生姓名,语文,数学,英语 这种格式显示学生成绩,如下图所示 具体步骤如下: 1.首先,使用case when函数输出单个课程的成绩 ca ...

  4. Android开发--多线程之Handler

    前言 Android的消息传递机制是另外一种形式的“事件处理”,这种机制主要是为了解决Android应用中多线程的问题,在Android中不 允许Activity新启动的线程访问该Activity里的 ...

  5. 经典c语言题

    1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 2. 写一个“标 ...

  6. C#判断VS是否处于设计模式

    public class CheckDesingModel { public static bool IsDesingMode() { bool ReturnFlag = false; if (Lic ...

  7. 0423 hashlib模块、logging模块、configparse模块、collections模块

    一.hashlib模块补充 1,密文验证 import hashlib #引入模块 m =hashlib.md5() # 创建了一个md5算法的对象 m.update(b') print(m.hexd ...

  8. 【反思】一个价值两天的BUG,无论工作还是学习C语言的朋友都看看吧!

    博文原创,转载请联系博主! 使用C语言也有两个年头了,BUG写出来过不少,也改过不少BUG.但是偏偏就是有这么一个BUG让我手头的项目停工了两天,原因从百度找到谷歌,资料从MAN手册找到RFC也没有找 ...

  9. 利用etcd及confd实现配置自动管理

    ETCD etcd 架设etcd集群 静态启动etcd集群需要每个成员在集群中知道另一个成员.在许多情况下,集群成员的IP可能提前未知.在这种情况下,可以使用etcd集群的自动发现服务.一旦etcd集 ...

  10. 大话设计模式--备忘录 Memento -- C++实现实例

    1. 备忘录: 在不破坏封装性的前提下, 捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后可将该对象恢复到原先保存的状态. Originator 发起人: 负责创建一个备忘录Memento ...