字符编码
文件的编码
编码
概念:规定每个“字符”采用一个字节还是多个字节来存储以及用哪些字节来存储。(通俗的说就是把“字符”转化成“字节”)
扫盲区:
- 位:(bit)
- 这里说的位就是指的二进制位了,也就是说的0或者1。他们都可以表示一位
- 字节:(byte)
- 计算机存储数据的一个单位
- 组成:由8个0或1组成也就是我们所谓的一个byte(字节)
- 实际上在Java中,byte就是一个0-255之间的整数
- 举个栗子:0x01, 0x45, 0xFA,.....
- 字符:
- 人们所使用的记号,抽象意义上的一个符号。
- 通俗的说就是我们平时看到的一切字母、符号、中文、法文、日文等等。c是个字符、中也是个字符。
- 一个字符的大小(也就是其所占的二进制位)是由编码规则决定的,
- 举个栗子:1', '中', 'a', '$', '¥', ……
要知道的:在计算机内部采用的是二进制进行存储,但是作为人呢,自然有自己的语言。因此为了让计算机能够看能我们的语言,就要采用一定的编码然后在发给计算机;计算机如果想要将信息呈现给我们看就要进行相应的解码。
- 字符-->字节(编码)encode
- 字节-->字符(解码)decode
字符集
定义: 将我们使用的字母、汉字、符号收入标准中;相当于一本大字典,这个字典里面有常用的字符相对应的二进制码。
“字符集”和“编码”一般都是同时制定的。因此,平常我们所说的“字符集”,比如:ISO-8859-1、UTF-8、GB2312, GBK, JIS 等,除了有“字符的集合”这层含义外,同时也包含了“编码”的含义。
编码格式 | 英文字符(所占字节数) | 汉字(所占字节数) |
---|---|---|
ISO-8859-1 | 1 | 1 |
ASCII | 1 | 2 |
GBK | 1 | 2 |
GB2312 | 1 | 2 |
UTF-8 | 1 | 3/4 |
UTF-16 | 4 | 2/4 |
字符编码发展
系统内码 | 编码标准 | 说明 | 系统 | |
---|---|---|---|---|
阶段一 | ASII | ISO-8859-1 | 胚胎级别的编码方式(最原始的啦)只支持英语,其它语言不能够在计算机上存储和显示 | DOS |
阶段二 | ANSI | GB2312,GBK, JISGB2312,BIG5,Shift_JIS, | 为使计算机支持更多语言,通常使用 0x80~0xFF 范围的 2 个字节来表示 1 个字符。比如:汉字 '中' 在中文操作系统中,使用 [0xD6,0xD0] 这两个字节存储。不同的国家和地区制定了不同的标准,由此产生了等各自的编码标准。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码 | 中文 DOS,中文 Windows 95/98,日文 Windows 95/98 |
阶段三 | UNICODE(国际化) | UTF-8,UTF-16, UnicodeBig …… | 为了使国际间信息交流更加方便,国际组织制定了 UNICODE 字符集,为各种语言中的每一个字符设定了统一并且唯一的数字编号,以满足跨语言、跨平台进行文本转换、处理的要求。 | Windows NT/2000/XP,Linux,Java |
常用的字符编码简介
-
ASCII(1字母1字节占8位)
问题:计算机只识别0或1,不识别符号
解决:既然不识别那就造一个”字典“给翻译成二进制代码。由于这个法子是美国人想到的所以计算机刚开始只支持英语,其它语言不能够在计算机上存储和显示。一个字母需要一个字节表示,也就是说占8位。这样的话有256种0和1的组合方式,可以表示256个不同的字母。对于,英文而言就绰绰有余了。
-
GB2312(1字母1字节;1汉字2字节)
问题:显然,美国人在设计ASCII码的时候没有考虑到遥远的东方,存在博大精深的文化。新华字典里面的汉字有多少个?显然256是远远不够的!那平方呢?65535?够了吧?还不够?
解决:于是就发明了GB2312这些汉字编码,典型的用2个字节来表示绝大部分的常用汉字,英文还是和ASCII保持一致占一个字节。
-
UNICODE(1字符多字节取决于编码格式)
问题:这下各用各的字符集编码,这世界咋统一?俄国人发封email给中国人,两边字符集编码不同,尼玛显示都是乱码啊。
解决:于是就发明了unicode,将世界上所有的符号都纳入其中,每一个符号都给予一个独一无二的编码,现在unicode可以容纳100多万个符号,每个符号的编码都不一样,这下可统一了,所有语言都可以互通,一个网页页面里可以同时显示各国文字。
这里就说到一个网络上经常出现的一个问题,UNICODE编码里面,一个汉字占几位的问题。很多老程序员会这么说:“一个汉字占两个字节!其实,很多时候,汉字占几个自己完全取决于编码格式。编码格式也不难写,因此对于汉字的编码有多种说法:ubuntu12.04里面一个汉字是三个字节!就是说,在unicode编码下,一个汉字可能是2个字节,也可能是3个或者是4个字节。“UNICODE 字符集”包含了各种语言中使用到的所有“字符”。用来给 UNICODE 字符集编码的标准有很多种,比如:UTF-8, UTF-7, UTF-16, UnicodeLittle, UnicodeBig 等。
-
utf8(1字母1字节;1汉字1-4字节)
问题:unicode虽然统一了全世界字符的二进制编码,但没有规定如何存储啊,亲。x86和amd体系结构的电脑小端序和大端序都分不清,别提计算机如何识别到底是unicode还是acsii了。如果Unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,文本文件的大小会因此大出二三倍,这对于存储来说是极大的浪费。这样导致一个后果:出现了Unicode的多种存储方式。
解决:即UTF-8不是固定字长编码的,而是一种变长的编码方式。它可以使用1~4个字节表示一个符号(注意”符号“中英文都有可能),根据不同的符号而变化字节长度。这是种比较巧妙的设计,如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。因此在utf8编码格式下,英文字母占一个字节,和ascii完全相同。汉字或者是其他字符占1-4个字节。
练习
/**
*
*@描述:字符的编码(字符-->字节)
* @param args
* @throws UnsupportedEncodingException
*/
public static void main(String[] args) throws UnsupportedEncodingException {
String msg = "相信自己";
//默认的是使用工程的编码格式
byte[] datas = msg.getBytes();
System.out.println(datas.length);
//将msg按照指定的字符集进行编码
byte[] datas1 = null;
datas1 = msg.getBytes("UTF-8");
System.out.println(datas1.length);
}
/**
*
* @描述:解码(字节-->字符)
*
* String(byte[] bytes)
通过使用平台的默认字符集解码指定的字节数组来构造新的 String 。
String(byte[] bytes, Charset charset)
构造一个新的String由指定用指定的字节的数组解码charset 。
String(byte[] bytes, int offset, int length)
通过使用平台的默认字符集解码指定的字节子阵列来构造新的 String 。
String(byte[] bytes, int offset, int length, Charset charset)
构造一个新的String通过使用指定的指定字节子阵列解码charset 。
String(byte[] bytes, int offset, int length, String charsetName)
构造一个新的 String通过使用指定的字符集解码指定的字节子阵列。
String(byte[] bytes, String charsetName)
构造一个新的String由指定用指定的字节的数组解码charset 。
*/
public class contentDecode {
public static void main(String[] args) throws UnsupportedEncodingException {
String msg = "相信自己!";
//使用utf-8进行编码
byte[] datas = msg.getBytes("utf-8");
System.out.println("utf-8编码后的结果:"+datas);
//使用utf-8进行解码
String info = new String(datas,"utf-8");
System.out.println("utf-8解码后的结果:"+info);
String info1 = new String(datas,"iso-8859-1");
System.out.println("iso-8859-1解码后的结果:"+info1);
System.out.println(datas.length);
String info2 = new String(datas,0,datas.length-3,"utf-8");
System.out.println(info2);
}
}