Java byte[]与基本数据类型之间的转换

在网络编程当中,常常会涉及到字节数组(buffer)的解析,与其他数据类型相互转换。

例如Socket,BLE等等。以下是字节数组与各种数据类型之间的大小端方式相互转换的Java实现工具类汇总。

大端:高地址存储低字节;
小端:低地址存储低字节。

例如:整形 0x12345678 (注意:0x12是高字节 ~ 0x78是低字节)
内存地址(字节数组下标 0 ~ 7)
大端:12 34 56 78
小端:78 56 34 12

如果转换设计无符号数据类型参考我的另一篇:Java无符号数据类型处理
Note:计算机系统默认小端方式存储,在日常开发当中,通常都是使用小端方式。

大端与小端的详细介绍就不在此详细阐述了。

代码如下,主要是比特位运算和Java的基本API实现,详细的设计编程语言基本数据类型与计算机数据存储原理,相信这些知识在教科书上也是有详述,附上简单的说明:
1、byte[] 与 short互相转换
2、byte[] 与 int互相转换
3、byte[] 与 float互相转换
4、byte[] 与 long互相转换
5、byte[] 与 double互相转换
6、byte[] 与 16进制字符串互相转换

/**
 * <pre>
 *     author : wushaohong
 *     date   : 2020-05-01
 *     desc   : 字节数组与基本数据类型的转换
 *              byte、short、int、float、long、double、16进制字符串
 *     version: 1.0
 * </pre>
 */

public class ByteArrayUtil {

    /**
     * 字节数组转 short,小端
     */
    public static short byteArray2Short_Little_Endian(byte[] array) {

        // 数组长度有误
        if (array.length > 2) {
            return 0;
        }

        short value = 0;
        for (int i = 0; i < array.length; i++) {
            // & 0xff,除去符号位干扰
            value |= ((array[i] & 0xff) << (i * 8));
        }
        return value;
    }

    /**
     * 字节数组转 short,大端
     */
    public static short byteArray2Short_Big_Endian(byte[] array) {

        // 数组长度有误
        if (array.length > 2) {
            return 0;
        }

        short value = 0;
        for (int i = 0; i < array.length ; i++) {
            value |= ((array[i] & 0xff) << ((array.length - i - 1) * 8));
        }
        return value;
    }

    /**
     * 字节数组转 int,小端
     */
    public static int byteArray2Int_Little_Endian(byte[] array) {

        // 数组长度有误
        if (array.length > 4) {
            return 0;
        }

        int value = 0;
        for (int i = 0; i < array.length; i++) {
            value |= ((array[i] & 0xff) << (i * 8));

        }
        return value;
    }

    /**
     * 字节数组转 int,大端
     */
    public static int byteArray2Int_Big_Endian(byte[] array) {

        // 数组长度有误
        if (array.length > 4) {
            return 0;
        }

        int value = 0;
        for (int i = 0; i < array.length ; i++) {
            value |= ((array[i] & 0xff) << ((array.length - i - 1) * 8));
        }
        return value;
    }

    /**
     * 字节数组转 float,小端
     */
    public static float byteArray2Float_Little_Endian(byte[] array) {

        // 数组长度有误
        if (array.length != 4) {
            return 0;
        }

        return Float.intBitsToFloat(byteArray2Int_Little_Endian(array));
    }

    /**
     * 字节数组转 float,大端
     */
    public static float byteArray2Float_Big_Endian(byte[] array) {

        // 数组长度有误
        if (array.length > 4) {
            return 0;
        }

        return Float.intBitsToFloat(byteArray2Int_Big_Endian(array));
    }

    /**
     * 字节数组转 long,小端
     */
    public static long byteArray2Long_Little_Endian(byte[] array) {

        // 数组长度有误
        if (array.length != 8) {
            return 0;
        }

        long value = 0;
        for (int i = 0; i < array.length ; i++) {
            // 需要转long再位移,否则int丢失精度
            value |= ((long)(array[i]& 0xff) << (i * 8));
        }
        return value;
    }

    /**
     * 字节数组转 long,大端
     */
    public static long byteArray2Long_Big_Endian(byte[] array) {

        // 数组长度有误
        if (array.length != 8) {
            return 0;
        }

        long value = 0;
        for (int i = 0; i < array.length ; i++) {
            value |= ((long)(array[i] & 0xff) << ((array.length - i - 1) * 8));
        }
        return value;
    }

    /**
     * 字节数组转 double,小端
     */
    public static double byteArray2Double_Little_Endian(byte[] array) {

        // 数组长度有误
        if (array.length != 8) {
            return 0;
        }

        return Double.longBitsToDouble(byteArray2Long_Little_Endian(array));
    }

    /**
     * 字节数组转 double,大端
     */
    public static double byteArray2Double_Big_Endian(byte[] array) {

        // 数组长度有误
        if (array.length != 8) {
            return 0;
        }

        return Double.longBitsToDouble(byteArray2Long_Big_Endian(array));
    }

    /**
     * 字节数组转 HexString
     */
    public static String byteArray2HexString(byte[] array) {

        StringBuilder builder = new StringBuilder();
        for (byte b : array) {

            String s = Integer.toHexString(b & 0xff);
            if (s.length() < 2) {
                builder.append("0");
            }
            builder.append(s);
        }

        return builder.toString().toUpperCase();
    }

    //---------------------------------华丽的分割线-------------------------------------

    /**
     * short 转字节数组,小端
     */
    public static byte[] short2ByteArray_Little_Endian(short s) {

        byte[] array = new byte[2];

        for (int i = 0; i < array.length; i++) {
            array[i] = (byte) (s >> (i * 8));
        }
        return array;
    }

    /**
     * short 转字节数组,大端
     */
    public static byte[] short2ByteArray_Big_Endian(short s) {

        byte[] array = new byte[2];

        for (int i = 0; i < array.length; i++) {
            array[array.length - 1 - i] = (byte) (s >> (i * 8));
        }
        return array;
    }

    /**
     * int 转字节数组,小端
     */
    public static byte[] int2ByteArray_Little_Endian(int s) {

        byte[] array = new byte[4];

        for (int i = 0; i < array.length; i++) {
            array[i] = (byte) (s >> (i * 8));
        }
        return array;
    }

    /**
     * int 转字节数组,大端
     */
    public static byte[] int2ByteArray_Big_Endian(int s) {

        byte[] array = new byte[4];

        for (int i = 0; i < array.length; i++) {
            array[array.length - 1 - i] = (byte) (s >> (i * 8));
        }
        return array;
    }

    /**
     * float 转字节数组,小端
     */
    public static byte[] float2ByteArray_Little_Endian(float f) {

        return int2ByteArray_Little_Endian(Float.floatToIntBits(f));
    }

    /**
     * float 转字节数组,大端
     */
    public static byte[] float2ByteArray_Big_Endian(float f) {

        return int2ByteArray_Big_Endian(Float.floatToIntBits(f));
    }

    /**
     * long 转字节数组,小端
     */
    public static byte[] long2ByteArray_Little_Endian(long l) {

        byte[] array = new byte[8];

        for (int i = 0; i < array.length; i++) {
            array[i] = (byte) (l >> (i * 8));
        }
        return array;
    }

    /**
     * long 转字节数组,大端
     */
    public static byte[] long2ByteArray_Big_Endian(long l) {

        byte[] array = new byte[8];

        for (int i = 0; i < array.length; i++) {
            array[array.length - 1 - i] = (byte) (l >> (i * 8));
        }
        return array;
    }

    /**
     * double 转字节数组,小端
     */
    public static byte[] double2ByteArray_Little_Endian(double d) {

        return long2ByteArray_Little_Endian(Double.doubleToLongBits(d));
    }

    /**
     * double 转字节数组,大端
     */
    public static byte[] double2ByteArray_Big_Endian(double d) {

        return long2ByteArray_Big_Endian(Double.doubleToLongBits(d));
    }

    /**
     * HexString 转字节数组
     */
    public static byte[] hexString2ByteArray(String hexString) {

        // 两个十六进制字符一个 byte,单数则有误
        if (hexString.length() % 2 != 0) {
            return null;
        }

        byte[] array = new byte[hexString.length() / 2];

        int value = 0;
        for (int i = 0; i < hexString.length(); i++) {

            char s = hexString.charAt(i);

            // 前半个字节
            if (i % 2 == 0) {
                value = Integer.parseInt(String.valueOf(s), 16) * 16;
            } else {
                // 后半个字节
                value += Integer.parseInt(String.valueOf(s), 16);
                array[i / 2] = (byte) value;
                value = 0;
            }
        }

        return array;
    }
}

上面的工具类,对号入座即可。除了字节比特位运算转换之外,还能够使用Java 的一个类进行基本数据类型的互转:

ByteBuffer

例子1:int转字节数组

        ByteBuffer byteBuffer = ByteBuffer.allocate(4);
        // 小端,如果不指定小端,ByteBuffer默认是大端 ByteOrder.BIG_ENDIAN
        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
        byteBuffer.putInt(2020);
        // 转成字节数组
        byteBuffer.array();

例子2:字节数组转 int

        byte[] array = new byte[]{-28, 7, 0, 0};
        ByteBuffer byteBuffer = ByteBuffer.allocate(4);
        // 小端
        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
        byteBuffer.put(array);
        // 在bytebuffer中读取一个 int
        System.out.println(byteBuffer.getInt(0));

以上是对byte数组转换的一些总结。

如有纰漏,有误,欢迎各位指正,在下感激万分。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345