JAVA的位运算应用-对于数据类型和字节数组的相互转换

JAVA位运算应用

一、位运算符区别

>>:逻辑右移 正数补0,负数补1,不改变正副
>>>:算术右移:高位补0,改变正副
<<:逻辑左移 最后一位是0补0,是1补1

二、数据类型转化为字节数组

无论是什么数据类型,在计算机中都以二进制形式存在。比如int类型,由四字节组成,通过一系列的位运算,可以获取他的某一位,放入字节数组中。

当前要转换的int类型的数为:
			A8		 	2B 			7A			4F
二进制表示:	00111000    00101011    01111010    01001111

当要取得每个字节时:只需要和11111111进行相与即可
如果要得到4F:
			10101000    00101011    01111010    01001111
			00000000	00000000	00000000	11111111
如果要得到7A:这个数右移8个单位
			00000000    10101000    00101011    01111010
			00000000	00000000	00000000	11111111
依次类推

我们可以发现,获取从低位到高位的字节时,需要转换的值都需要向右进行移动,且是算数右移

public static byte[] getBytes(int value) {
    byte[] res = new byte[4];
    for (int i = 0; i < res.length; i++) {
        res[i] = (byte)((value >>> (i<<3)) & 0xFF);
    }
    
    return res;
}

三、字节数组转换为基础数据类型

还是之前的那个例子

将这串二进制转换为int类型
		10101000    00101011    01111010    01001111
	
这里我们从高位开始,每次i和高位进行按位与,后面一步一步的向前移动,我们需要注意的是,当一个字节进行自动类型转换的时候,会根据高位的数字进行补齐。那么10101000会变为
        11111111	11111111	11111111	10101000
    |   00000000	00000000	00000000	00000000
结果为   11111111	  11111111	  11111111	  10101000
这种结果是我们不希望看见的,所以在相或之前,应该和0xFF进行按位与
		11111111	11111111	11111111	10101000
      & 00000000	00000000	00000000	11111111
      	00000000	00000000	00000000	10101000
之后结果向左进行移位,和倒数第二个字节数进行相或
		00000000	00000000	10101000	00000000
     |  00000000	00000000	00000000	00101011
        00000000	00000000	10101000	00101011
依次类推,就得到了真正的int数值

字节数组中高位应该先赋值给int类型中的低字节,再通过将int左移操作将其一步步挪到高位上。
当取出字节数组中的一个元素并将其和int按位或时,该8位二进制会被自动补全为4*8=32位二进制,而补的是符号位,固需要考虑符号位为1时,防止数据出错,固需要额外一步和0xFF按位与,只取出最低位即可。

public static int bytesToInt(Byte[] bytes) {
    int res = 0;
    
    for (int i = 0; i < 4; i++) {
        res <<= 8;
        res |= (bytes[4 - i - 1] & 0xFF);
    }
    
    return res;
}

四、数据类型和字节数组的相互转换的代码

/**
 * @Author :漠殇
 * @Data :Create in 11:41 2021/8/4
 */
public class BytesTransfer {
    private static final int SHORT_BYTE_COUNT = 2;
    private static final int INT_BYTE_COUNT = 4;
    private static final int LONG_BYTE_COUNT = 8;

    public BytesTransfer() {
    }

    /**
     * 将int类型数据转换为字节数组
     * @param value 需要转换的int类型数据
     * @return 该数据转换的字节数组
     */
    public static byte[] toBytes(int value) {
        byte[] res = new byte[INT_BYTE_COUNT];

        for (int i = 0; i < res.length; i++) {
            res[i] = (byte) ((value >>> (i << 3)) & 0xFF);
        }
        return res;
    }

    /**
     * 将int型数据转换成二进制,加到数组 {@code bytes}
     * 中从 {@code offset} 开始的地方
     *
     * @param value 需要转换的int型数据
     * @return 添加数据后的二进制数组
     */
    public static byte[] toBytes(int value, long offset, byte[] bytes) {
        for (int i = 0; i < 4; i++) {
            bytes[i + offset] = (byte) ((value >>> (i << 3)) & 0xFF);
        }

        return bytes;
    }

    /**
     * 将字节数组转化为int类型的数据
     * @param bytes 需要转换的字节数组
     * @return 转换的int类型 的值
     */
    public static int bytesToInt(byte[] bytes) {
        if (bytes.length != BytesTransfer.INT_BYTE_COUNT) {
            throw new InvalidBytesNumberException("bytes length [" +
                    bytes.length + "] is not 4, can't transfer to [int].");
        }
        int res = 0;

        for (int i = 0; i < 4; i++) {
            res <<= 8;
            res |= (bytes[4 - i - 1] & 0xFF);
        }
        return res;
    }

    /**
     * 将二进制数组 {@code bytes} 从 {@code offset} 起后四位,
     * 放到一个临时字节数组中,然后调用 bytesToInt(byte[] bytes)转换
     *
     * @param bytes 需要转换的二进制数组
     * @param offset 起始下标偏移量
     * @return 转换的 int型 值
     */
    public static int bytesToInt(byte[] bytes, long offset) {
        if (bytes.length - offset < BytesTransfer.INT_BYTE_COUNT) {
            throw new InvalidBytesNumberException("bytes rest length [" +
                    (bytes.length - offset) + "] is less than 4, can't transfer to [int].");
        }
        byte[] tmp = new byte[4];
        for (int i = 0; i < 4; i++) {
            tmp[i] = bytes[offset + i];
        }

        return bytesToInt(tmp);
    }

    /**
     * 将long类型数据转换为字节数组
     * @param value 需要转换的long类型数据
     * @return 该数据转换的字节数组
     */
    public static byte[] toBytes(long value) {
        byte[] res = new byte[LONG_BYTE_COUNT];

        for (int i = 0; i < res.length; i++) {
            res[i] = (byte) ((value >>> (i << 3)) & 0xFF);
        }
        return res;
    }

    /**
     * 将long型数据转换成二进制,加到数组 {@code bytes}
     * 中从 {@code offset} 开始的地方
     *
     * @param value 需要转换的long型数据
     * @return 添加数据后的二进制数组
     */
    public static byte[] toBytes(long value, long offset, byte[] bytes) {
        for (int i = 0; i < 8; i++) {
            bytes[i + offset] = (byte) ((value >>> (i << 3)) & 0xFF);
        }

        return bytes;
    }

    /**
     * 将字节数组转化为long类型的数据
     * @param bytes 需要转换的字节数组
     * @return 转换的long类型 的值
     */
    public static long bytesToLong(byte[] bytes) {
        if (bytes.length != BytesTransfer.LONG_BYTE_COUNT) {
            throw new InvalidBytesNumberException("bytes length [" +
                    bytes.length + "] is not 8, can't transfer to [long].");
        }
        long res = 0;

        for (int i = 0; i < 8; i++) {
            res <<= 8;
            res |= (bytes[8 - i - 1] & 0xFF);
        }

        return res;
    }

    /**
     * 将二进制数组 {@code bytes} 从 {@code offset} 起后八位,
     * 放到一个临时字节数组中,然后调用 bytesToInt(byte[] bytes)转换
     *
     * @param bytes 需要转换的二进制数组
     * @param offset 起始下标偏移量
     * @return 转换的 long型 值
     */
    public static long bytesToLong(byte[] bytes, long offset) {
        if (bytes.length - offset < BytesTransfer.LONG_BYTE_COUNT) {
            throw new InvalidBytesNumberException("bytes rest length [" +
                    (bytes.length - offset) + "] is less than 8, can't transfer to [long].");
        }
        byte[] tmp = new byte[8];
        for (int i = 0; i < 8; i++) {
            tmp[i] = bytes[offset + i];
        }

        return bytesToLong(tmp);
    }


    /**
     * 将short类型数据转换为字节数组
     * @param value 需要转换的short类型数据
     * @return 该数据转换的字节数组
     */
    public static byte[] toBytes(short value) {
        byte[] res = new byte[SHORT_BYTE_COUNT];

        for (int i = 0; i < res.length; i++) {
            res[i] = (byte) ((value >>> (i << 3)) & 0xFF);
        }
        return res;
    }

    /**
     * 将short型数据转换成二进制,加到数组 {@code bytes}
     * 中从 {@code offset} 开始的地方
     *
     * @param value 需要转换的long型数据
     * @return 添加数据后的二进制数组
     */
    public static byte[] toBytes(short value, short offset, byte[] bytes) {
        for (int i = 0; i < 2; i++) {
            bytes[i + offset] = (byte) ((value >>> (i << 3)) & 0xFF);
        }

        return bytes;
    }


    /**
     * 将字节数组转化为short类型的数据
     * @param bytes 需要转换的字节数组
     * @return 转换的short类型 的值
     */
    public static short bytesToShort(byte[] bytes) {
        if (bytes.length != BytesTransfer.SHORT_BYTE_COUNT) {
            throw new InvalidBytesNumberException("bytes length [" +
                    bytes.length + "] is not 2, can't transfer to [short].");
        }
        short res = 0;

        for (int i = 0; i < 2; i++) {
            res <<= 8;
            res |= (bytes[2 - i - 1] & 0xFF);
        }

        return res;
    }

    /**
     * 将二进制数组 {@code bytes} 从 {@code offset} 起后二位,
     * 放到一个临时字节数组中,然后调用 bytesToInt(byte[] bytes)转换
     *
     * @param bytes 需要转换的二进制数组
     * @param offset 起始下标偏移量
     * @return 转换的 long型 值
     */
    public static int bytesToShort(byte[] bytes, long offset) {
        if (bytes.length - offset < BytesTransfer.SHORT_BYTE_COUNT) {
            throw new InvalidBytesNumberException("bytes rest length [" +
                    (bytes.length - offset) + "] is less than 2, can't transfer to [short].");
        }
        byte[] tmp = new byte[2];
        for (int i = 0; i < 2; i++) {
            tmp[i] = bytes[offset + i];
        }

        return bytesToShort(tmp);
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值