JAVA deep binary


概述

本文主要介绍java的二进制处理和相关的底层基础问题探索

JAVA的基础数据类型8种

类型 位数 字节数 范围
byte 8位 1字节 -128(-2^7) — 127(2^7 - 1
short 16位 2字节 -32768(-2^15)— 32767(2^15 - 1)
int 32位 4字节 -2,147,483,648(-2^31) — -2,147,483,647(2^31 - 1)
long 64位 8字节 默认值0L
float 32位 4字节 默认值0.0f
double 64位 8字节 默认值0.0d
boolean 1位 默认值false
char 16位 2字节 Unicode字符 \u0000(0) — \uffff(65535)

位运算运算符

类型 计算方式 速记方式
& 10101010 & 01010101 = 00000000 有0为0,出现0则为0
| 10101010 | 01010101 = 11111111 有1为1,出现1则为1
^ 10101010 ^ 01010101 = 11111111 合2为1,出现不同则为1,相同则为0
~ ~10101010 = 0101010101 1变为0,0变为1
<< 10101010 << 0xFF 左移0xFF位,右补0相当与*2
>> 10101010 >> 0xFF 有符号右移0xFF位,正数高位补0,负数补1
>>> 10101010 >>> 0xFF 无符号右移0xFF位,高位全部补0

基础类型说明

从上面我们可以发现JAVA和C的差异,C语言整数默认是signed有符号的,C语言中也可用unsigned 表示一个无符号值,JAVA整数都是有符号的,但也可通过一些方式表示无符号值。

如何用JAVA表示C语言的正确值

java提供了一种方式来表示 C的 unsigned int short等, 如何实现,对当前的数据进行&运算,和谁?
具体和谁需要看你的数据类型,0xff的二进制是1111 1111 (8bit)

    public int getUnsignedByte (byte data){ //将data字节型数据转换为0~255 (0xFF 即BYTE),
        return data & 0x0FF ; //int 4字节 32位 表示将高24位全部变为0,保留低8位原始值,变为有符号首位为0的值,相当于C的有符号值
    } 
    public int getUnsignedByte (short data){ //将data字节型数据转换为0~65535 (0xFFFF 即WORD)。 
        return data & 0x0FFFF ; //int 4字节 32位 表示将高16位全部变为0,保留低16位原始值,变为有符号首位为0的值,相当于C的有符号值
    } 
    public long getUnsignedIntt (int data){ //将int数据转换为0~4294967295 (0xFFFFFFFF即DWORD)。 
        return data & 0x0FFFFFFFF ; //long 8字节 64位 表示将高32位全部变为0,保留低32位原始值,变为有符号首位为0的值,相当于C的有符号值
    }

负数的二进制

在计算机中,正数是以原码的形式存储的,而负数是以补码的形式存储的,负数的二进制需要该数正数按位取反的值再+1.

详解>>>预算符

负数int -20无符号右移:r = -20 >>> 2

注:数据类型默认为int 32位

    -20://负数的二进制需要该数正数按位取反的值再+1.
    源码:10000000  00000000   00000000   00010100

    反码:11111111  11111111   11111111   11101011//反码后+1

    补码:11111111  11111111   11111111   11101100 

    右移:00111111  11111111   11111111   11111011

    结果:r = 1073741819

^交换 a b 值

        a=a∧b;
        b=b∧a;
        c=a∧b;

大端模式和小端模式

  1. 大端模式:Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

    低地址 ——————–> 高地址
    0x12 | 0x34 | 0x56 | 0x78

  2. 小端模式:Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

    低地址 ——————–> 高地址
    0x78 | 0x56 | 0x34 | 0x12

  3. 常见的CPU字节序

    Big Endian : PowerPC、IBM、Sun
    Little Endian : x86、DEC
    ARM既可以工作在大端模式,也可以工作在小端模式
    JAVA和大部分的网络通讯协议都是使用Big-Endian的编码.

  4. 常见文件的字节序

    Adobe PS – Big Endian
    BMP – Little Endian
    DXF(AutoCAD) – Variable
    GIF – Little Endian
    JPEG – Big Endian
    MacPaint – Big Endian
    RTF – Little Endian

  5. 读取存储数据的顺序

    不管是大端还是小端模式,我们在读取和存储数据的时候一定都是从内存的低地址依次向高地址读取或写入。[ps这句话非常重要,请注意理解]

A内存地址 A存储的值
0x2000 4001 0x01
0x2000 4002 0x02
0x2000 4003 0x03
0x2000 4004 0x04

如果现在大端模式A传递此数据给B小端模式
A将内存中的值取出,取值由内存的低地址往高地址取值,由于大端模式的内存低位地址(即0X01)对应字节数组高位值,则字节数组最高位(最左边位)为[0x01,X,X,X],则传递值为0x1234。

B接收到字节数组在内存中存储的时候也是按照内存低地址往高地址开始依次存储,由于小端模式的内存低位地址(即0x04)对应字节数组低位值,则在B中内存存储的数据为:

B内存地址 B存储的值
0x8000 4001 0x04
0x8000 4002 0x03
0x8000 4003 0x02
0x8000 4004 0x01

B将内存中的值取出,取值由内存的低地址往高地址取值,则字节数组最低位(最右边位)为[X,X,X,0x1],则取出值为0x4321.

为什么在内存中同样的存储,取到的值不一样呢,因为此数组是4个字节,按照小端模式取出来的值则不一样,如果字节序一样则值相同,如果只是单字节,也是相同的,不需要关心顺序。

会发现数据由A传递给B后其显示的数据发生了翻天覆地的变化,这就是为啥在处理网络数据的时候要确定字节序的原因,必须保证A和B的字节序相同,如果不同,就需要使用字节序的转换函数。

如何理解JAVA的有符号 [1byte -128 - 127]

举个栗子:JAVA的一个byte8位表示为10000001, C语言的一个byte8位表示为10000001
这个byte在JAVA和C中代表了不同的值JAVA > -1 C > -129为什么?
因为JAVA作为有符号其左边第一位用来表示正负值,第一位为1表示为一个负数,其表示的实际值为-1,而C语言左边第一位仍然表示数值其值为2^7 + 1 = 129 ,java 则为-1.

异或加密和解密

      /**
         * xor 加密 key=xxxxxxxxxx
        * @Description:
        * @param data
        * @return
         */
        public  byte[] xorEncode(byte[] data){  

             for(int i = 0; i < data.length; ++i){  
                 data[i] ^= keyBytes[i%keyBytes.length];  
             }  

             return data;  

        }  


        /**
         * xor 解密 key=1234567890
        * @Description:
        * @param data
        * @return
         */
        public  byte[] xorDecode(byte[] data){

            for(int i = 0; i < data.length; ++i){  
                data[i] ^= keyBytes[i%keyBytes.length];  
            }  
            return data;
        }

JAVA byte[] TO short 的大小端和无符号相互转换

        /** 
         * @功能 字节的转换与短整型  小端模式
         * @param 两位的字节数组 
         * @return 短整型 
         */  
        public  short byteToShort(byte[] b) {  
            short s = 0;  
            short s0 = (short) (b[0] & 0xff);// 最低位  
            short s1 = (short) (b[1] & 0xff);  
            s1 <<= 8;  //byte数组低位值左移8位
            s = (short) (s0 | s1);  
            return s;  
        }  

        /** 
         * @功能 字节的转换与短整型  大端模式
         * @param 两位的字节数组 
         * @return 短整型 
         */  
        public  short byteToShort_BIG(byte[] b) {  
            short s = 0;  
            short s0 = (short) (b[1] & 0xff);// 最低位  
            short s1 = (short) (b[0] & 0xff);  
            s1 <<= 8;  //byte数组低位值左移8位
            s = (short) (s0 | s1);  
            return s;  
        }  

        /** 
         * @功能  字节转换为短整型 无符号short
         * @param 两位的字节数组 
         * @return 短整型 
         */  
        public  int byteToUnSinghedShort(byte[] b) {  
            short s = 0;  
            short s0 = (short) (b[0] & 0xff);// 最低位  
            short s1 = (short) (b[1] & 0xff);  
            s1 <<= 8;  //byte数组低位值左移8位
            s = (short) (s0 | s1);  
            return s & 0xFFFF;  // short 所以和0xFFFF做&运算
        }  

        /** 
         * @功能 短整型与字节数组的转换 小端模式
         * @param 短整型 
         * @return 两位的字节数组 
         */  
        public  byte[] shortToByte(short number) {  
            int temp = number;  
            byte[] b = new byte[2];  
            for (int i = 0; i < b.length; i++) {  
                b[i] = new Integer(temp & 0xff).byteValue();// 将最低位保存在最低位  
                temp = temp >> 8; // 向右移8位  
            }  
            return b;  
        }  


        /** 
         * @功能 短整型与字节数组的转换 大端模式
         * @param 短整型 
         * @return 两位的字节数组 
         */  
        public  byte[] shortToByte_Big(short number) {  
            int temp = number;  
            byte[] b = new byte[2];  
            for (int i = 0; i < b.length; i++) {  
                b[b.length - i - 1] = new Integer(temp & 0xff).byteValue();// 将最低位保存在最高位
                temp = temp >> 8; // 向右移8位  
            }  
            return b;  
        }  

一盏灯, 一片昏黄; 一简书, 一杯淡茶。 守着那一份淡定, 品读属于自己的寂寞。 保持淡定, 才能欣赏到最美丽的风景! 保持淡定, 人生从此不再寂寞。



   Reprint policy


《JAVA deep binary》 by jackromer is licensed under a Creative Commons Attribution 4.0 International License
 Previous
python的一次pip异常解决 python的一次pip异常解决
概述 一次运行Pip 安装Python库的时候突然报错了,试了很多种办法,终于找到正解,记录记录. 错误详情 执行pip install 的时候报错 看起来像是没有找到正确的Python.exe error:unable to crea
2019-08-27
Next 
JAVA关键字解读 JAVA关键字解读
概述 本文主要介绍JAVA的一些比较难以理解的关键字和用法 protected 关键字protected定义 顾明思议,因为受保护,但是保护的范围是有限的,可以保护所处的包,子类和自己.限制了使用范围.如果希望超类中的某些方法允许被子类
2019-08-27
  目录