ASCII编码原 编码知识整理 传统编码方案

前言
   可能很多人事先没有了解好相关的编码知识,就把Unicode编码和UTF-8编码混为一谈相互比较,认为是两种不同的编码,其实不然,Unicoe编码只是一个字符集,规定了字符和二进制代码的对应关系,好比是一个大字典,但是对于如何编码存储在计算机及其具体实现,Unicode编码并没有做规定,而UTF-8编码就是Unicode编码的一种实现方式,它定义了解析存储的一整套编码规则,所以,就关系而言,Unicode和UTF-8编码并不能做横线比较,说到底,UTF-8编码只是实现Unicode编码的一种实现方法,并没有重新定义字符和二进制代码的二进制关系。

介绍
   Unicode编码的出现,是为了解决各个地区定义字符编码混乱而制定的一套业界标准,在Unicode编码出现之前,也出现过各式各样本土化的编码,如下所示:

编码名称    占用字节数
ASCII    一个字节
GBK    两个字节
   ASCII编码相信是大部分人最熟悉的编码之一,它是西欧编码,仅仅用一个字节表示字符,这也难怪,因为西欧大部分英文国家字符集不大,ASCII编码已经足够用了,但是到了中国,光是汉字就有几万个,ASCII编码完全不够用,所以GBK编码由此产生,使用两个字节定义一个字符,这样就可以定义六万多个字符。 
   这些不同地区使用的字符编码,如果只是区域内使用,是完全没有问题的,但是一旦跨地域使用不同的编码方法,那么就会产生各种各样的展示问题,俗称乱码。当然现实生活并没有这个问题,因为现实生活如纸张这种载体,能够存放的字符没有限制,而因为计算机载体的特殊性,只识别和存放得了01两个字符,所以所有的字符经过编码转化最终都是以01存放在计算机内部,因此编码不同,解析字符的规则自然不同,所以导致展示出来的字符就不相同了,就会有乱码的可能性。 
   所以编码规则本质上就是字符的解析规则,下面看几个概念:

字符
字符是可使用多种不同字符方案或代码页来表示的抽象实体。也可以理解为字符是一个编码方案的一个最小单位。

字符集合
字符集合是字符总和的集合,如Unicode字符集,GBK字符集,ASCII字符集

字符编码
字符编码是一种规则,为了方便互联网传输,字符编码定义了二进制和字符的对应规则

   综合上述这几个概念,所以无论是ASCII编码也好,GBK编码也好,本质上都是为了二进制和字符的转而诞生的,而Unicode只算得上是字符集合,具体的字符编码就是UTF-8编码。UTF-8是一种变长的编码方式,规则如下:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。 
2)对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。

所以使用UTF-8,英文字母还是占用一个字节,而依据Unicode字符集,大部分中文都是占用了三个字节,不过在早期的互联网中,英文还是占据大部分,因而UTF-8编码占用的字符消耗并不算大。后续也出现了UTF-16等新的编码方式,为了节约某些场景的存储消耗。

场景
windows txt 保存文本 “你好,世界” 默认编码格式为ansi ,ansi编码介绍如下:
不同的国家和地区制定了不同的标准,由此产生了 GB2312、GBK、Big5、Shift_JIS 等各自的编码标准。这些使用 1 至 4 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。 不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。 当然对于ANSI编码而言,0x00~0x7F之间的字符,依旧是1个字节代表1个字符。这一点是ANSI编码与Unicode编码之间最大也最明显的区别。

所以在windows上面就是gbk编码,借助OKio读取如下:

    public static void main(String[] args) throws Exception {
      System.out.println("默认字符集  " + Charset.defaultCharset().name());

      File file = new File("files_holder/test-ansi.txt");
      BufferedSource source = Okio.buffer(Okio.source(file));

      System.out.println(source.readString(Charset.defaultCharset()).toString());
    }
1
2
3
4
5
6
7
8
输出如下:

默认字符集  GBK
你好,世界
1
2
使用了默认的字符编码去读取字节,默认的字符编码是GBK,由此可知我使用的这台windows的ansi编码就是GBK编码。 
如果使用utf8编码去读取字节,输出则是如下:

默认字符集  GBK
????????
1
2
出现了乱码。 
2. windows txt 保存文本 “你好,世界”, 选择编码格式为utf8

    public static void main(String[] args) throws Exception {
      System.out.println("默认字符集  " + Charset.defaultCharset().name());

      File file = new File("files_holder/test-utf8.txt");
      BufferedSource source = Okio.buffer(Okio.source(file));

      System.out.println(source.readString(Charset.forName("utf-8")).toString());

    }
1
2
3
4
5
6
7
8
9
10
输出如下:

默认字符集  GBK
?你好,世界
1
2
神奇的是,输出多了一个?,这个问号是什么呢,使用进制查看工具winhex,查看如下 
 
按理说,应该是十五个字节,但是总共有十八个字节,并且前三个字节不可见,查阅资料可知,在windows的文本编辑器保存utf8格式时,会增加BOM标识符,也就是前面三个字节,所以我们在文件流读取utf8格式时,要切记BOM标识符,避免程序出错。

参考
彻底弄懂 Unicode 编码

展开阅读全文 
--------------------- 
作者:少年阿涛 
来源:CSDN 
原文:https://blog.csdn.net/taoszu/article/details/82528573 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值