JAVA实现Python中struct.pack()和struct.unpack()方法,并增加比特类型支持_java struct.pack_Jelly_dong的博客-程序员资料

技术标签: JAVA  


package jelly.command.coder.util;

import jelly.command.coder.exception.CmdCodecException;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;
import org.apache.commons.lang3.ArrayUtils;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

public class CoderUtil {

    public static void main(String[] args) throws Exception {
        String pattern = "h2,h4,s,h4,i";
        System.out.println(pattern);
        String value = "621E,0000FEB1,29,FFFFFFFF,21";
        System.out.println(value);
        String encode = HexBin.encode(encode(pattern, value, false));
        System.out.println(encode);
        System.out.println(String.join(",",decode(pattern,HexBin.decode(encode),false)));

    }

    public static List<String> getSrcCode(byte[] bytes, String pattern) throws CmdCodecException {
        pattern = pattern.replace("i", "i4")
                .replace("s", "s2")
                .replace("f", "f4")
                .replace("l", "l8");
        boolean hasBit = pattern.contains("b");
        byte[] bits = BitUtils.bytesToBits(bytes);
        ByteBuffer bytesBuf = ByteBuffer.wrap(bytes);
        bytesBuf.position(0);
        ByteBuffer bitsBuf = ByteBuffer.wrap(bits);
        bitsBuf.position(0);
        List<String> srcCodeList = new ArrayList<>();
        String[] pa = pattern.split(",");
        for (String s : pa) {
            String type = s.substring(0, 1);
            int len = Integer.parseInt(s.substring(1));
            byte[] bytesTemp;
            len = hasBit && !type.equals("b") ? len * 8 : len;
            bytesTemp = new byte[len];
            if (hasBit) {
                bitsBuf.get(bytesTemp, 0, len);
            } else {
                bytesBuf.get(bytesTemp, 0, len);
            }
            switch (type) {
                case "i":
                case "s":
                case "l":
                case "f":
                case "h":
                    srcCodeList.add(HexBin.encode(hasBit ? BitUtils.bitsToBytes(bytesTemp) : bytesTemp));
                    break;
                case "b":
                    StringBuilder sb = new StringBuilder();
                    for (byte b : bytesTemp) sb.append(b);
                    srcCodeList.add(sb.toString());
                    break;
                default:
                    throw new CmdCodecException("not support this type : " + type);
            }
        }
        return srcCodeList;
    }


    /**
     * @param pattern 字节数组的属性格式
     *                例如:i,s,l,h4,b8,其中h和b后面需要指定字节长度
     *                i:表示4个字节的int
     *                s:表示2个字节的short,
     *                l:表示8个字节的long,
     *                h4:表示4个字节的16进制,
     *                b8:表示8个比特
     * @param value   各属性的标示值,用“,”分割。例如:"2,3,4,A1B1C1D1,00001111"
     * @return 组合后的字节数组
     * @throws CmdCodecException 不支持类型
     */
    public static byte[] encode(String pattern, String value, boolean isLittleEndian) throws CmdCodecException {
        pattern = pattern.replace("i", "i4")
                .replace("s", "s2")
                .replace("f", "f4")
                .replace("l", "l8");
        String[] parArr = pattern.split(",");
        String[] vaArr = value.split(",");
        boolean hasBit = pattern.contains("b");
        List<byte[]> bytesList = new ArrayList<>();
        for (int i = 0; i < parArr.length; i++) {
            String type = parArr[i].substring(0, 1);
            String num = parArr[i].substring(1);
            int len = Integer.parseInt(num);
            String strValue = vaArr[i];
            byte[] bytes;
            switch (type) {
                case "i":
                    bytes = Ints.toByteArray(Integer.parseInt(strValue));
                    if (isLittleEndian) ArrayUtils.reverse(bytes);
                    bytesList.add(hasBit ? BitUtils.bytesToBits(bytes) : bytes);
                    break;
                case "s":
                    bytes = Shorts.toByteArray(Short.parseShort(strValue));
                    if (isLittleEndian) ArrayUtils.reverse(bytes);
                    bytesList.add(hasBit ? BitUtils.bytesToBits(bytes) : bytes);
                    break;
                case "f":
                    float[] floats = {Float.parseFloat(strValue)};
                    bytes = ByteUtils.floatArrToByteArr(floats);
                    if (isLittleEndian) ArrayUtils.reverse(bytes);
                    bytesList.add(hasBit ? BitUtils.bytesToBits(bytes) : bytes);
                    break;
                case "l":
                    bytes = Longs.toByteArray(Long.parseLong(strValue));
                    if (isLittleEndian) ArrayUtils.reverse(bytes);
                    bytesList.add(hasBit ? BitUtils.bytesToBits(bytes) : bytes);
                    break;
                case "h":
                    bytes = HexBin.decode(strValue);
                    byte[] bytes1 = new byte[len];
                    System.arraycopy(bytes, 0, bytes1, len - bytes.length, bytes.length);
                    if (isLittleEndian) ArrayUtils.reverse(bytes1);
                    bytesList.add(hasBit ? BitUtils.bytesToBits(bytes1) : bytes1);
                    break;
                case "b":
                    bytes = new byte[strValue.length()];
                    for (int k = 0; k < strValue.length(); k++) {
                        bytes[k] = Byte.parseByte(String.valueOf(strValue.charAt(k)));
                    }
                    bytes1 = new byte[len];
                    System.arraycopy(bytes, 0, bytes1, len - bytes.length, bytes.length);
                    bytesList.add(bytes);
                    break;
                default:
                    throw new CmdCodecException("not support this type : " + type);
            }
        }
        int len = 0;
        for (byte[] bytes : bytesList) {
            len += bytes.length;
        }
        ByteBuffer buffer = ByteBuffer.allocate(len);
        for (byte[] bytes : bytesList) {
            buffer.put(bytes);
        }
        return hasBit ? BitUtils.bitsToBytes(buffer.array()) : buffer.array();
    }

    public static String[] decode(String pattern, byte[] bytes, boolean isLittleEndian) throws CmdCodecException {
        pattern = pattern.replace("i", "i4")
                .replace("s", "s2")
                .replace("f", "f4")
                .replace("l", "l8");
        boolean hasBit = pattern.contains("b");
        byte[] bits = BitUtils.bytesToBits(bytes);
        ByteBuffer bytesBuf = ByteBuffer.wrap(bytes);
        bytesBuf.position(0);
        ByteBuffer bitsBuf = ByteBuffer.wrap(bits);
        bitsBuf.position(0);
        String[] parArr = pattern.split(",");
        String[] resultArr = new String[parArr.length];
        for (int i = 0; i < parArr.length; i++) {
            String s = parArr[i];
            String type = s.substring(0, 1);
            int len = Integer.parseInt(s.substring(1));
            byte[] bytesTemp;
            len = hasBit && !type.equals("b") ? len * 8 : len;
            bytesTemp = new byte[len];
            if (hasBit) {
                bitsBuf.get(bytesTemp, 0, len);
            } else {
                bytesBuf.get(bytesTemp, 0, len);
            }
            byte[] tmp = hasBit ? BitUtils.bitsToBytes(bytesTemp) : bytesTemp;
            if (isLittleEndian){
                ArrayUtils.reverse(tmp);
            }
            switch (type) {
                case "i":
                    resultArr[i] = String.valueOf(Ints.fromByteArray(tmp));
                    break;
                case "s":
                    resultArr[i] = String.valueOf(Shorts.fromByteArray(tmp));
                    break;
                case "l":
                    resultArr[i] = String.valueOf(Longs.fromByteArray(tmp));
                    break;
                case "f":
                    resultArr[i] = String.valueOf(ByteUtils.byteArrToFloatArr(tmp)[0]);
                    break;
                case "h":
                    resultArr[i] = HexBin.encode(tmp);
                    break;
                case "b":
                    StringBuilder sb = new StringBuilder();
                    for (byte b : bytesTemp) sb.append(b);
                    resultArr[i] = sb.toString();
                    break;
                default:
                    throw new CmdCodecException("not support this type : " + type);
            }
        }
        return resultArr;
    }
}

相关工具类

package jelly.command.coder.util;

import com.google.common.primitives.Ints;
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;

import java.util.Arrays;

/**
 * @Date 2020/12/26 17:08
 * @Version 1.0
 * @Description
 */
public class BitUtils {

    public static void main(String[] args) {
        System.out.println(Arrays.toString(hexStrToBits("0013")));
        System.out.println(bitStrToHex("00000010011"));
    }

    public static byte bitStrToByte(String bitStr) {
        int re, len;
        if (bitStr == null) {
            return 0;
        }
        len = bitStr.length();
        if (len != 4 && len != 8) {
            return 0;
        }
        if (len == 8) {//8 bit 处理
            if (bitStr.charAt(0) == '0') {
                re = Integer.parseInt(bitStr, 2);
            } else {//负数
                re = Integer.parseInt(bitStr, 2) - 256;
            }
        } else { //4 bit 处理
            re = Integer.parseInt(bitStr, 2);
        }

        return (byte) re;
    }

    public static String byteToBitStr(byte by) {
        return ""
                + (byte) ((by >> 7) & 0x1) + (byte) ((by >> 6) & 0x1)
                + (byte) ((by >> 5) & 0x1) + (byte) ((by >> 4) & 0x1)
                + (byte) ((by >> 3) & 0x1) + (byte) ((by >> 2) & 0x1)
                + (byte) ((by >> 1) & 0x1) + (byte) ((by) & 0x1);
    }

    public static byte[] byteToBitByByteArr(byte by) {
        byte[] bits = new byte[8];
        for (int i = 7; i >= 0; i--) {
            bits[i] = (byte) (by & 1);
            by = (byte) (by >> 1);
        }

        return bits;
    }

    public static byte[] bitsToBytes(byte[] bits) {
        byte[] temp;
        if (bits.length < 8) {
            temp = new byte[8];
            System.arraycopy(bits, 0, temp, 8 - bits.length, bits.length);
        } else {
            temp = bits;
        }
        byte[] bytes = new byte[temp.length / 8];
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < temp.length; i++) {
            sb.append(temp[i]);
            if (sb.length() == 8) {
                bytes[i / 8] = bitStrToByte(sb.toString());
                sb.delete(0, 8);
            }
        }
        return bytes;
    }

    public static byte[] bitsToBytes(String bits) {
        char[] chars = bits.toCharArray();
        byte[] bytes = new byte[chars.length];
        for (int i = 0; i < chars.length; i++) {
            bytes[i] = Byte.parseByte(String.valueOf(chars[i]));
        }
        return bitsToBytes(bytes);
    }


    /**
     * byte to bit array by Boolean array
     *
     * @param by
     * @return
     */
    public static boolean[] byteToBitByBooleanArr(byte by) {
        boolean[] bits = new boolean[8];
        for (int i = 7; i >= 0; i--) {
            bits[i] = (by & 1) == 1;
            by = (byte) (by >> 1);
        }
        return bits;
    }

    /**
     * 字节数组转换成以字节表示为比特的数组
     *
     * @param bytes
     * @return
     */
    public static byte[] bytesToBits(byte[] bytes) {
        byte[] temp = new byte[bytes.length * 8];
        for (int i = 0; i < bytes.length; i++) {
            byte[] bits = byteToBitByByteArr(bytes[i]);
            System.arraycopy(bits, 0, temp, i * 8, 8);
        }
        return temp;
    }

    public static byte[] hexStrToBits(String hex) {
        if (hex.contains("H")) {
            hex = hex.replace("H", "");
        }
        return bytesToBits(ByteUtils.hexToBytes(hex));
    }

    public static String hexStrToBits(String hex, int len) {
        if (hex.contains("H")) {
            hex = hex.replace("H", "");
        }
        byte[] bits = bytesToBits(ByteUtils.hexToBytes(hex));
        int hexLen = hex.length() * 4;
        StringBuilder sb = new StringBuilder();
        if (hexLen >= len) { //取后len位
            for (int i = bits.length - len; i < bits.length; i++) {
                sb.append(bits[i]);
            }
        } else {//前面填充0
            for (int i = 0; i < len - hexLen; i++) {
                sb.append("0");
            }
            for (byte bit : bits) {
                sb.append(bit);
            }
        }
        return sb.toString();
    }


    public static String bitStrToHex(String param) {
        //前面需要填充0的个数
        int remain = param.length() % 8;
        int num = 0;
        if (remain > 0) {
            num = 8 - remain;
        }
        String bits = param;
        if (num > 0) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < num; i++) {
                sb.append(0);
            }
            sb.append(param);
            bits = sb.toString();
        }
        return HexBin.encode(bitsToBytes(bits));
    }

    /**
     * 截取后len位bit
     *
     * @param value
     * @param len
     * @return
     */
    public static String intToBits(int value, int len) {
        StringBuilder sb = new StringBuilder();
        byte[] bits = bytesToBits(Ints.toByteArray(value));
        for (int i = bits.length - len; i < bits.length; i++) {
            sb.append(bits[i]);
        }
        return sb.toString();
    }

}


package jelly.command.coder.util;

import com.google.common.primitives.Ints;

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

/**
 * @Date 2020/12/23 10:55
 * @Version 1.0
 * @Description
 */
public class ByteUtils {
    private static final char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7',
            '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};



    public static void main(String[] args) {
        System.out.println(revertHex("ABCDDEFH"));
    }

    public static byte[] hexToBytes(String hex) {
        if (hex == null || hex.length() == 0) {
            return null;
        }
        char[] chars = hex.toCharArray();
        byte[] bytes = new byte[chars.length / 2];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) Integer.parseInt("" + chars[i * 2] + chars[i * 2 + 1], 16);
        }
        return bytes;
    }


    public static String bytesToHex(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        StringBuilder hex = new StringBuilder();

        for (byte b : bytes) {
            hex.append(hexDigits[(b >> 4) & 0x0F]);
            hex.append(hexDigits[b & 0x0F]);
        }
        return hex.toString();

    }

    /**
     * 反转
     *
     * @param source
     * @param begin
     * @param length
     * @return
     */
    public static byte[] arraySliceAndReverse(
            byte[] source,
            int begin,
            int length) {
        byte[] tempArr = new byte[source.length];
        System.arraycopy(source, 0, tempArr, 0, source.length);
        byte temp;
        for (int i = 0; i < (source.length - length) / 2; i++) {
            temp = tempArr[begin + i];
            tempArr[begin + i] = tempArr[source.length - i - 1];
            tempArr[source.length - i - 1] = temp;
        }
        return tempArr;
    }


    /**
     * 已测试
     *
     * @param bytes
     * @return
     */
    public static int bytesToInt(byte[] bytes) {
        byte[] temp = new byte[Integer.BYTES];
        if (bytes.length < 4) {
            System.arraycopy(bytes, 0, temp, temp.length - bytes.length, bytes.length);
        } else if (bytes.length > 4) {
            System.arraycopy(bytes, bytes.length - 4, temp, 0, Integer.BYTES);
        }
        return Ints.fromByteArray(temp);
    }

    public static String bytesToString(byte[] bytes, char placeholder) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            if (b == (byte) placeholder) {
                break;
            }
            sb.append((char) b);
        }
        return sb.toString();
    }

    /**
     * String -> bytes array
     *
     * @param param       原字符串
     * @param length      bytes 数组长度
     * @param placeholder 数组空余位置填充
     * @return 字节数组
     */
    public static byte[] stringToBytes(String param, int length, char placeholder) {
        byte[] rawContent = new byte[length];
        char[] array = param.toCharArray();
        int len = Math.min(array.length, length);
        for (int i = 0; i < len; i++) {
            rawContent[i] = (byte) array[i];
        }
        for (int i = array.length; i < length; i++) {
            rawContent[i] = (byte) (placeholder);
        }
        return rawContent;
    }

    public static String revertHex(String hex) {
        StringBuilder sb = new StringBuilder();
        for (int i = hex.length() - 1; i >= 0; i -= 2) {
            sb.append(hex, i - 1, i + 1);
        }
        return sb.toString();
    }

    public static float[] byteArrToFloatArr(byte[] bytes) {
        ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
        FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
        float[] aFloat = new float[floatBuffer.limit()];
        floatBuffer.get(aFloat);
        return aFloat;
    }

    public static byte[] floatArrToByteArr(float[] floats) {
        ByteBuffer buffer = ByteBuffer.allocate(floats.length * 4);
        FloatBuffer floatBuffer = buffer.asFloatBuffer();
        floatBuffer.put(floats);
        return buffer.array();
    }


}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Jelly_dong/article/details/119821045

智能推荐

消息中间件——RabbitMQ(三)理解RabbitMQ核心概念和AMQP协议!_dfp51711的博客-程序员资料

前言本章学习,我们可以了解到以下知识点:互联网大厂为什么选择RabbitMQ?RabbiMQ的高性能之道是如何做到的?什么是AMQP高级协议?AMQP核心概念是什么?RabbitMQ整体架构模型是什么样子的?RabbitMQ消息是如何流转的?1. 初识RabbitMQRabbitMQ 是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据...

【java】异常,try...catch语句,finally语句,throws关键字,throw关键字,非受查异常和受查异常_Wweakness的博客-程序员资料

java提供了异常处理机制来帮助程序员检查可能出现的错误,java中将异常封装到一个类中,出现错误时,就会抛出异常。【异常】:异常是指程序在允许时产生的错误,例如进行除法运算时,若除数为0时,则运行就会抛出算数异常;若对一个值为null的引用变量进行操作,则会抛出空指针异常;若访问一个大小为2的一维数组中的第3个元素,则会抛出数组下标越界的异常。java中异常也是通过一个对象来表示的,...

maven配置文件settings.xml理解使用_小李须努力的博客-程序员资料

文章目录**localRepository**:**interactiveMode**:**offline**:**pluginGroups**:**proxies**:**servers**:**mirrors**:**profiles**:**activation**:**properties**:**repositories**:**pluginRepository**:**activeProfiles**:在安装好maven之后,我们一般不使用maven默认的配置,比如本地仓库、阿里云私服地址等;

老司机开车,教会女朋友「马拉车算法」的正确姿势_吴师兄学算法的博客-程序员资料

马拉车算法( Manacher‘s Algorithm )是程序员小吴最喜欢的算法之一,因为,它真的很牛逼! 马拉车算法是用来 查找一个字符串的最长回文子串的线性方法 ,由一个叫 Manacher 的人在 1975 年发明的,这个方法的牛逼之处在于将时间复杂度提升到了 线性 。 事实上,马拉车算法在思想上和 KMP 字符串匹配算法有相似之处,都避免做了很多重复的工作...

Cost-Effective Federated Learning Design论文笔记_RUI!的博客-程序员资料

Cost-Effective Federated Learning Design论文笔记

Fiddler抓包工具手机添加代理后连不上网解决办法_fd抓包手机上不了网_数据结构和算法的博客-程序员资料

想看更多算法题,可以扫描上方二维码关注我微信公众号“数据结构和算法”,截止到目前我已经在公众号中更新了500多道算法题,其中部分已经整理成了pdf文档,截止到目前总共有800多页(并且还会不断的增加),可以在公众号中回复关键字“pdf”即可下载。原文链接:https://blog.csdn.net/shuiziliu1025/article/details/80911811 最近,在工作中需要测试一个监..

随便推点

三面外包经验,这次春招有幸获得京东内推机会,历经四面成功收下offer!_架构师阿彬的博客-程序员资料

前言受限感谢在网上提供面经大佬们,本人211本,末流985渣硕。本人一共参加了今年的春招和秋招提前批,春招拿到了几个offer因为一点原因都没有去,然后因为朋友推荐的关系,现在准备就签京东了。附上面试的面经京东一面:面向对象的优点将对象进行分类,分别封装它们的数据和可以调用的方法,方便了函数、变量、数据的管理,方便方法的调用(减少重复参数等),尤其是在编写大型程序时更有帮助。用面向对象的编程可以把变量当成对象进行操作,让编程思路更加清晰简洁,而且减少了很多冗余变量的出现java的特点(1)Jav

python爬虫学习笔记_kerreny的博客-程序员资料

爬虫学习笔记爬虫学习笔记1.网页页面获取爬虫学习笔记这是 学习北理的mooc教程的笔记。1.网页页面获取简易爬虫框架import requesturl = ' 'try: kv={'user-agent':'Mozilla/5.0'} #将爬虫伪装成浏览器 r = request.get(url.header=kv) r.raise_for_status() r.encodi...

电大计算机应用基础网考小抄,2016年12月份电大计算机应用基础网考小抄(已排版直接打印版).doc..._weixin_39710561的博客-程序员资料

PAGEPAGE 10计算机应用基础网考 (已排版直接打印版)选择题1、一般认为,世界上第一台电子数字计算机诞生于1946年。2、计算机当前已应用于各种行业、各种领域,而计算机最早的设计是针对科学计算。3、计算机有多种技术指标,其中决定计算机的计算精度的是字长_。4、自计算机问世至今已经经历了四个时代,划分时代的主要依据是计算机的构成元件。5、世界上第一台电子数字计算机采用的逻辑元件是电子管。...

在Windows8安装winpcap的问题_win8安装xcap无法刷新接口_choujs的博客-程序员资料

Wireshark是最常用的网络抓包工具,其底层依赖于Winpcap软件用于实现抓包。Winpcap目前最新版本是4.1.2版,该版本在windows8下安装时会提示有兼容性问题并推出安装。其实Winpcap 4.1.2是支持Windows8的,需要将安装程序的兼容性设为Windows7(右键-->属性-->兼容性),出现兼容性提示界面后选择继续安装就可以正常安装。安装完成后可以正常使用。

adf4351 锁相环相关硬件设计_qq_42748149的博客-程序员资料

ADF4351锁相环介绍及相关硬件设计ADF4351是ADI公司推出的一款集成VCO的锁相环芯片。其输出频率范围可配置为35MHZ到4400MHZ,这取决于参考频率和寄存器配置。其内部包括整数N分频器和小数N分频器,可配置参考频率,对于输出频率也可采用输出可编程分频器进行分频。其供电电压为3-3.6V,一般采用3.3V供电。采用4/5或8/9预分频器可对频率细分,其控制接口采用三线式串行接口,由于集成VCO以及控制接口简单,整个PLL设计相对简单。下面将详细介绍如何对ADF4351设计,本节主要介绍硬件

自动驾驶中的时间同步方案_自动驾驶 时间同步-程序员资料

tbox自动驾驶完整时间同步方案 gpsd pps chrony ptpd

推荐文章

热门文章

相关标签