字节码的整理

为什么要编码?

不知道大家有没有想过一个问题,为什么要编码,不编码可以吗? 明确回答,NO。计算机世界只有0和1二进制编码,其基本存储单元也是byte(字节)来表示。但人类语言太多,无法用byte来全部表示,毕竟byte只有8位,能表示256个字符。所以需要一些翻译工作,各国根据自己语言特性,都想制定标准,所以就有个多种编码格式。
char是为了解决这种上述问题出现的,char转byte是编码,byte转char是解码。

相关基础知识点

  1. 字符(Character)
    各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。

  2. 字符集(Character Set)
    字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。

  3. 字符编码(Character Encoding)
    是一套法则,使用该法则能够对自然语言的字符的一个集合。

几种常见的编码格式

ASCII
ASCII字符集:主要包括控制字符(回车键、退格、换行键等)(范围是十进制是0到31);可显示字符(英文大小写字符、阿拉伯数字和西文符号)(范围是十进制32-127)。
ASCII编码:使用低7位(bits)表示一个字符,共128字符. 这128个字符组成基本的编码字符。但是局限性很大,无法表示大量的字符,所以并不是广泛使用。

ISO-8859-1
ISO组织在ASCII码基础上又制定了一系列的标准来扩展ASCII编码,其中ISO-8859-1就是一种,它是单字节编码,总共能够表示256个字符。

GB2312
适用于中文的一种编码格式,属于双字节编码,也就是一个汉字字符需要两个字节来表示。表现的汉字不超过7000个。

GBK
基于GB2312,也是双字节编码,可以表示21003个汉字。用GB2312编码的汉字可以用GBK来编码。

UTF-16
为了能够使世界上所有的语言都通过一种编码方式来互相转换吗,制定了Unicode(统一编码),Unicode是Java和XML的基础。UTF-16定义了Unicode在计算机中的存取方式,顾名思义16表示2Bit,也就是一个字符由两个字节表示,不够的用00补全,所以使用UTF-16字符集,编码和解码都很方便。但是存在一个明显的问题,存储空间扩大了一倍,在非常邮有限的网络带宽中,会很容易的增大网络传输的流量。

UTF-8
为了解决UTF-16的浪费存储空间问题,出现了UTF-8这种变长的编码方式,英文字符用1个byte表示,中文字符用3个byte表示。不同类型的字符可以由1-6个字节组成。

在哪些场景会使用到编码?

  1. 在IO操作中存在字符编码
    IO操作主要包括,磁盘IO和网络IO。在网络传输前,需要进行编码,以二进制流形式在网络中传输,然后接收方进行解码。

  2. 在内存操作中存在字符编码
    除了IO外,最常见的是内存中从字符到字接的数据类型转换。

    String s = "人民的名义";
    byte[] bytes = s.getbytes("UTF-8");// 没有指定编码方式时,则采用系统默认的编码方式。
    String news = new String(bytes, "UTF-8");// 解码方式
    

    StringCoding 类提供了String字符串和byte数组之间的转换接口
    static byte[] encode(String charsetName, char[] ca, int off, int len) static char[] decode(String charsetName, byte[] ba, int off, int len)
    这两个接口是由StringCoding的内部类StringDecoder 和 StringEncoder 分别定义的decode和encode方法来实现,而内部类中的decode和encode方法又是由CharsetEncoder和CharSetDecoder中的encode和decode方法实现,最终这两个方法是由相应类中定义的抽象方法
    public final CoderResult encode(CharBuffer in, ByteBuffer out, boolean endOfInput);
    protected abstract CoderResult decodeLoop(ByteBuffer in,CharBuffer out);
    来实现,所以会根据charsetName找到相应的CharSet对象,并找出继承了抽象类CharSetEncoder或CharSetDecoder类的子类中实现的方法来实现。

CharSet类
CharSet chaeSet = Charset.forName(String charSetName) ; // 根据传入的字符集名称,生成相应字符集类型的对象。注意这里虽然使用forName但是并不是反射,跟踪源码可以知道,其实最终是通过查找缓存找到的,跟Class类中的forName不一样。
在CharSet类中,存在两个接口。
ByteBuffer encode(CharBuffer cb);
CharBuffer decode(ByteBuffer bb);
可以实现char[] 和 byte[]之间的转换。

CharSet charset = CharSet.forName("UTF-8");
ByteBuffer byteBuffer = charset.encode(String);
CharBuffer charBuffer = charset.decode(byteBuffer);

注意:其实CharSet是UTF-16、UTF-8、GBK等字符集的抽象父类,它们都继承了它。

byte 字节
char 字符
字节和字符的区别?
GBK
UTF-8
UTF-16

常用编码方式的比较:
encode (编码)
decode (解码)

什么情况下出现乱码? 如何避免?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值