二进制、计算机编码、位运算

整理一下二进制、计算机编码、位运算相关知识,拒绝含糊不清

主要设计三个基本数据类型 byte、int、char

以16进制表示查看二进制文件
xxd file
反码、补码:

https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html

上面虽然解释了 反码,补码,但是还是有一些问题没有解释清楚:为什么负数的补码是反码+1,为什么正数的补码还是本身,-128的补码为什么是10000000等等,请看下面👇

https://www.cnblogs.com/esmusssein/p/11182321.html

字符编码:

https://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/

Java 判断本地主机字节序工具:ByteOrder.nativeOrder();
大端小端在一台机器上没感知,因为高位地位是确定的,只不过在有的机器上内存的高地址对应高位叫“小端字节序” 像x86架构,而有的是内存的高地址对应低位叫“大端字节序”。

Unicode 编码查询工具:

https://www.qqxiuzi.cn/bianma/Unicode-UTF.php

Java内码是utf-16吗?

https://blog.csdn.net/u014631304/article/details/77509380

关于Unicode更多理解:

https://www.jianshu.com/p/ad4bff4d9fa3

Java编码扩展知识:

https://www.jianshu.com/p/1b00ca07b003

理解byte负数:

https://blog.csdn.net/csdn_ds/article/details/79106006

& 0xff 获取真值原理:

https://blog.csdn.net/i6223671/article/details/88924481

常用工具代码:
  1. byte 转 二进制表示
    /**
     * byte 转 二进制表示
     * @param b
     * @return
     */
    public static String byteToBit(byte b) {
        return ""
                + (byte) ((b >> 7) & 0x1) + (byte) ((b >> 6) & 0x1)
                + (byte) ((b >> 5) & 0x1) + (byte) ((b >> 4) & 0x1)
                + (byte) ((b >> 3) & 0x1) + (byte) ((b >> 2) & 0x1)
                + (byte) ((b >> 1) & 0x1) + (byte) ((b >> 0) & 0x1);
    }
  1. 获取byte指定位的值
    /**
     * 获取byte指定位的值
     * @param b
     * @param i (i>=1)
     * @return
     */
    public static byte getBitArray(byte b,int i) {
        return (byte) ((b >> (8-i)) & 0x1);
    }
  1. 字节数组转16进制
    /**
     * 字节数组转16进制
     * @param bytes 需要转换的byte数组
     * @return  转换后的Hex字符串
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if(hex.length() < 2){
                sb.append(0);
            }
            sb.append(hex);
        }
        return sb.toString();
    }
  1. char 转 byte数组(JVM大端转化的结果,非真实内存存放顺序)
    /**
     * char 转 byte数组
     * @param c
     * @return
     */
    public static byte[] charToByte(char c) {
        byte[] b = new byte[2];
        b[0] = (byte) ((c & 0xFF00) >> 8);
        b[1] = (byte) (c & 0xFF);
        return b;
    }
  1. 16进制 转 字节数组
 	/**
     * 16进制 转 字节数组
     * @param hexString
     * @return
     */
    public static byte[] hexString2Bytes(String hexString) {
        BiFunction<Byte, Byte, Byte> uniteBytes = (src0, src1) -> {
            char b0 = (char) Byte.decode("0x" + new String(new byte[] {src0})).byteValue();
            b0 = (char) (b0 << 4);
            char b1 = (char) Byte.decode("0x" + new String(new byte[] {src1})).byteValue();
            return (byte) (b0 ^ b1);
        };
        int size = hexString.length();
        byte[] ret = new byte[size / 2];
        byte[] tmp = hexString.getBytes();
        for (int i = 0; i < size / 2; i++) {
            ret[i] = uniteBytes.apply(tmp[i * 2], tmp[i * 2 + 1]);
        }
        return ret;
    }
  1. byte数组 转 int
    /**
     * byte数组 转 int
     * @param bytes
     * @return
     */
    public static int bytes2Int(byte[] bytes) {
        int result = 0;
        //将每个byte依次搬运到int相应的位置
        result = bytes[0] & 0xff;
        result = result << 8 | bytes[1] & 0xff;
        result = result << 8 | bytes[2] & 0xff;
        result = result << 8 | bytes[3] & 0xff;
        return result;
    }
  1. int 转 byte数组
    /**
     * int 转 byte数组
     * @param num
     * @return
     */
    public static byte[] int2Bytes(int num) {
        byte[] bytes = new byte[4];
        //通过移位运算,截取低8位的方式,将int保存到byte数组
        bytes[0] = (byte) (num >>> 24);
        bytes[1] = (byte) (num >>> 16);
        bytes[2] = (byte) (num >>> 8);
        bytes[3] = (byte) num;
        return bytes;
    }
  1. 获取String内存中对应的 UTF-16 编码的byte数组 (JVM大端转化的结果,非真实内存存放顺序)
    /**
     * 获取String内存中对应的 UTF-16 编码的byte数组 
     * @param str
     * @return
     */
    public static byte[] string2bytes(String str) {
        ByteBuffer heapByteBuffer = ByteBuffer.allocate (str.length() * 2);
        for (char c : str.toCharArray()) {
            heapByteBuffer.putChar(c);
        }
        heapByteBuffer.flip();

        int len = heapByteBuffer.limit() - heapByteBuffer.position();
        byte[] bytes = new byte[len];
        heapByteBuffer.get(bytes);
        return bytes;
    }
  1. 通过Unsafe查看字符在内存中的实际顺序(非JVM优化过的,我认为这才是内存真实存放的顺序,取决于具体的CPU架构)

    @SuppressWarnings("restriction")
    static private sun.misc.Unsafe getUnsafe() throws IllegalArgumentException, IllegalAccessException {
        Class<?> cls = sun.misc.Unsafe.class;
        Field[] fields = cls.getDeclaredFields();
        for (Field f : fields) {
            if ("theUnsafe".equals(f.getName())) {
                f.setAccessible(true);
                return (sun.misc.Unsafe) f.get(null);
            }
        }
        throw new IllegalAccessException("no declared field: theUnsafe");
    }

    /**
     * 查看字符在内存中真实的顺序,非JVM优化的,取决于CPU架构
     * @param ch
     * @return
     * @throws IllegalAccessException
     */
    public static byte[] char2bytesNative(char ch) throws IllegalAccessException {
        byte[] bytes = new byte[2];
        Unsafe unsafe = getUnsafe();
        long address = unsafe.allocateMemory(2);
        unsafe.putChar(address, ch);
        byte b = unsafe.getByte(address);
        bytes[0] = b;
        b = unsafe.getByte(address + 1);
        bytes[1] = b;
        return bytes;
    }

    public static void main(String[] args) throws Throwable {
       	System.out.println(bytes2HexString(charToByte('国')));
      	System.out.println(bytes2HexString(char2bytesNative('国')));
    }

    /**
     * 还有一种更直接的方法
     * @param ch
     * @return
     * @throws IllegalAccessException
     */
    public static byte[] char2bytesNative2(char ch) throws IllegalAccessException {
        Unsafe unsafe = getUnsafe();
        char[] charArr = new char[1];
        charArr[0] = ch;
        byte b = unsafe.getByte(charArr, (long) (unsafe.arrayBaseOffset(charArr.getClass())));
        
        byte[] bytes = new byte[2];
        bytes[0] = b;
        b = unsafe.getByte(charArr, (long) (unsafe.arrayBaseOffset(charArr.getClass()) + 1));
        bytes[1] = b;
        return bytes;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值