从byte(字节)的bit(位)层面去理解编码(玩爆底层篇)

简介: 从byte(字节)的bit(位)层面去理解编码(玩爆底层篇)

话不多说,直接上干货

干货结论:

  • java不论是负数还是正数在定义、存储、计算的过程中,都是用其补码
  • 第二个结论需要自己去体会,详情看下面的2.从byte(字节)的bit(位)层面去理解编码

论证说明:

1.Byte类型用二进制八进制十六进制定义数值类型数据举例

用byte存一个负数,比如负27,我们一般情况下用十进制可以这样表示:

byte b1 = -27;

那么用二进制如何去声明负27这个数呢?用气原码,反码,还是补码去声明呢?
我们都知道负27这个数,其:
原码:1001 1011
反码:1110 0100
补码:1110 0101
这里我先直接告诉大家,定义-27这个数的时候用的是补码,存储到内存的时候也是用的补码,参与运算的时候到cpu的通用寄存器中的也是补码。
用二进制(0b)存储-27声明如下:

byte b2 = (byte) 0b11100101;

用八进制(0)存储-27声明如下:

byte b3 = (byte) 0345;

ps:
-27的补码二进制1110 0101转八进制:从后往前每三位二进制的数为一组,高位不足补零,划分为:011 100 101,八进制为:345(八进制)

用十六进制(0x)存储-27声明如下:

byte b4 = (byte) 0xe5;

ps:
-27的补码二进制1110 0101转十六进制:从后往前每四位二进制的数为一组,高位不足补零,划分为:1110 0101,十六进制为:e5(十六进制)

2.从byte(字节)的bit(位)层面去理解编码

2.1Unicode编码与UTF-8编码的关系

Unicode编码:Unicode(统一码、万国码)它是一种理论层面的东西。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。UTF-8编码:是Unicode编码的具体实现,它的UTF-8以字节为单位对Unicode进行编码。
以下是UTF-8的形式:
0xxxxxx
说明:它是可变长编码,出现频率较多的字符,如ASCII中的字符,通常是一个字节,这样节省存储空间110xxxxx 10xxx1110xxxx 10xxxxxx 10xxxxxx
说明:汉字通常是3个字节11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

ps: xx…x解读:其中一个x对应到Unicode编码中的一bit(位)

UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。

2.2用汉字举例,Unicode编码对应到UTF-8编码

我们可以去查这个字,它的Unicode编码为:55bb(十六进制)
把它转换成二进制为: 0101 0101 1011 1011
的Unicode编码为2个字节占16位,对应到UTF-8的时候,我们需要用到上面2.1中提到的1110xxxx 10xxxxxx 10xxxxxx这种形式,把0101 0101 1011 1011按位填入到xxx中,即把1110xxxx 10xxxxxx 10xxxxxx中的x用0101 0101 1011 1011替换掉。
替换后的结果为:11100101 10010110 10111011
这就是其UTF-8编码,用十六进制表示为:e596bb(十六进制)

java代码举例:用byte数组定义汉字:

public class StringDemo {
        
    public static void main(String[] args) {
        
        //二进制形式
        byte[] bytes = {
        (byte) 0b11100101,(byte) 0b10010110,(byte) 0b10111011};
        //也可以写成十六进制形式
        //byte[] bytes = {(byte)0xe5,(byte)0x96,(byte)0xbb};
        System.out.println(Arrays.toString(bytes));
        System.out.println(binary(bytes,16));

        try {
        
            String s = new String(bytes, 0, bytes.length, "UTF-8");
            System.out.println(s);
        } catch (UnsupportedEncodingException e) {
        
            e.printStackTrace();
        }
    }

    public static String binary(byte[] bytes,int radix){
        
        return new BigInteger(1,bytes).toString(radix);
    }
}

测试输出结果:
在这里插入图片描述

目录
相关文章
|
3月前
|
存储 网络协议 C语言
一文带你秒懂 字节序(byte order),比特序(bit order),位域(bit field)
一文带你秒懂 字节序(byte order),比特序(bit order),位域(bit field)
52 0
|
10月前
使用base64对图片进行编码、对byte[]进行编码
使用base64对图片进行编码、对byte[]进行编码
54 0
|
11月前
|
存储 Java
java基础类型中的char和byte的辨析及Unicode编码和UTF-8的区别
java基础类型中的char和byte的辨析及Unicode编码和UTF-8的区别
150 0
Java中字节Byte和位Bit的关系
Java中字节Byte和位Bit的关系
|
Python
Python编程:chardet模块检测byte字节编码
Python编程:chardet模块检测byte字节编码
123 0
|
存储
密码学之Byte和bit
密码学之Byte和bit
239 0
密码学之Byte和bit
|
JSON Java 关系型数据库
常见Serialize技术探秘(ObjectXXStream、XML、JSON、JDBC byte编码、Protobuf)
目前业界有各种各样的网络输出传输时的序列化和反序列化方案,它们在技术上的实现的初衷和背景有较大的区别,因此在设计的架构也会有很大的区别,最终在落地后的:解析速度、对系统的影响、传输数据的大小、可维护性及可阅读性等方面有着较大的区别,本文分享一些我在一些常见序列化技术的分析和理解: 文章分成3个部分: 1、列举常见的序列化和反序列化方案(ObjectXXStream、XML、JSON) 2、M
1677 0