ASCII,ISO8859-1,GBK,GB18030,Unicode,UTF-8详解

4 篇文章 0 订阅

概念

  计算机只认识0101这样的二进制字节,而人天生只对a,b.c,中,大这些字符敏感,而且写代码的目的是为了让计算机能读懂,主题是计算机,所以自然就衍生出了两个概念,如图1;

  • 编码(encode): 从字符到字节;
  • 解码(decode): 从字节到字符;

  那解码和编码也不能瞎解,瞎编吧,必须要有规范的对照的转化字典表吧,因为世界各地语言存在差异,编码和解码的工作也就不一样,就出了不同的字符集编码解码大字典,如 ASCII,ISO8859-1,GBK,GB18030,Unicode,UTF-8;
在这里插入图片描述

图1 编码和解码概念

ASCII,ISO8859-1,GBK,GB18030,Unicode,UTF-8详解

  程序中经常遇到乱码的问题,产生的乱码的原因就是因为计算机直接存储字符,需要将字符转化为二进制的,不同的转化规则就对应了不同的编码方式,而保持不乱的条件就是编码方式和解码方式保持一致,今天就一起阅尽天下编码,心中自然无码。
  首先先来看一眼编码的发展历程图,如图2:

编码发展历程图

图2 字符集编码发展历程

ASCII:首先大家都知道计算机由美国人发明,那ASCII码正是最早用来将127字符的编码到计算机里面的一套编码;
ISO8859-1:ASCII的扩充,可以编码一些较为生僻的拉丁字符;
GB2312:当计算机来到中国,ISO8859-1显然就不够用了,存储不了我们伟大的汉字,最找也有提出将汉字转化为拼音存入计算机的想法,但经过国人的不屑努力,开发出了GB2312的国内最早,用得最多的简体中文编码;
BIG5:与此同时港澳台同胞开发了BIG5来编码繁体汉字;
GBK:GB2312的扩充,把BIG5码的思想融入进来,既可以表示简体中文也可以表示繁体中文;
GB18030:GBK的扩充,可以表示少数民族的字符,现在的国标码;
Shift_JIS/Euc_kr:深受我大中华文化熏陶的周边国家日本,韩国方块象形字,在计算机引进后一样遇到了这样的问题,就自己开发了各自的国标码;
Unicode:每个国家都来一套国标码,那大家还怎么记?最重要跨国合作项目还做不做?因为大家的项目编码不同的话一样遇到乱码的,于是天下大事分久必合,Unicode诞生了;
UTF-8:Unicode已经满足要求了啊,为啥还有UTF-8,那是因为Unicode使用2个字节,但对于老美的字母存储来说,一个字节完全够用,用Unicode强行加大存储负担,本来ASCII码,1T的内容,强行被Unicode整出了2T,但是现在中,日,韩等象形字国家这么多,老美又避免不了和他们网络交流,于是UTF-8可变长的编码就诞生了,UTF-8,一个字节表示字母,3个字节普通汉字,4~6个字节表示生僻字;
UTF-16:定长,两个字节的unicode,分为大端(高段位地址)和小端(低段位地址),FF PE表示小端,FE FF表示大端;
  下表是常用的编码和表示汉字或字母时的字节数:

编码字母汉字
ISO8859-1/ASCII1个字节无法表示
GBK/GB18030/Unicode2个字节通常的2个字节(生僻字4个字节)
UTF-81个字节通常的3个字节(生僻字4~6个字节)

乱码的原因

  综上所述,乱码的原因一般就两个;

  1. 编码解码字符集不一致;

常人遇到的一般是这种,只需要另存为一下换成对应的字符集即可解决;

  1. 编码解码字符集一致了,但是该字符集所要覆盖的字节长度没有得到满足,发生了截断;

程序员处理程序有bug所致,需要给到适应的字节长度;

Java代码为例说明乱码

package cm.rowyet.Test17IO;

import java.io.UnsupportedEncodingException;

public class FileDemo06 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String msg="a,努力努力再努力!";

        System.out.println("---------------------编码后字节数----------------------------");
        //编码,字节数组
        byte[] datas=msg.getBytes(); //使用默认工程的字符集 默认为UTF-8
        System.out.println(datas.length);


        System.out.println("---------------------解码后字符----------------------------");
        System.out.println();
        //正确解码
        //String(byte[] bytes,int offset, int length,String charsetName);
        //byte[] bytes 字节数组;
        //offset 开始解析的位置
        //length 字节长度
        //charsetName 字符集
        msg=new String(datas,0,datas.length,"utf8");
        System.out.println(msg);

        System.out.println("---------------------字节数不够导致的解码乱码----------------------------");
        //乱码 字节数不够
        msg=new String(datas,0,datas.length-1,"utf8");
        System.out.println(msg);
        msg=new String(datas,0,datas.length-2,"utf8");
        System.out.println(msg);

        System.out.println("---------------------字符集不统一导致的解码乱码----------------------------");
        //字符集不统一
        msg=new String(datas,0,datas.length,"gbk");
        System.out.println(msg);


    }

}


  输出结果为:

---------------------编码后字节数----------------------------
24
---------------------解码后字符----------------------------

a,努力努力再努力!
---------------------字节数不够导致的解码乱码----------------------------
a,努力努力再努力
a,努力努力再努�
---------------------字符集不统一导致的解码乱码----------------------------
a,鍔姏鍔姏鍐嶅姫鍔�!

Process finished with exit code 0

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

╭⌒若隐_RowYet——大数据

谢谢小哥哥,小姐姐的巨款

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值