ToB企服应用市场:ToB评测及商务社交产业平台

标题: Java实现对象转成字节数组(整型支持按位写入,字符串则按字节写入) [打印本页]

作者: 十念    时间: 2024-4-14 20:41
标题: Java实现对象转成字节数组(整型支持按位写入,字符串则按字节写入)
闲着无聊,写了一个对象转换成byte[]的工具类,支持整型按位写入(大大节省空间),具体步骤如下:
1. 定义实体类和注解
  1. public class User {
  2.     /**
  3.      * ID,4个字节,32bit
  4.      */
  5.     @JSONField(ordinal = 1)
  6.     @BitPos(offset=0,size = 32)
  7.     public int id;
  8.     /**
  9.      * 姓名,10个字节(80bit)
  10.      */
  11.     @JSONField(ordinal = 2)
  12.     @BitPos(offset = 32, size= 80)
  13.     public String name;
  14.     /**
  15.      * 性别,0:男,1:女,1Bit
  16.      */
  17.     @JSONField(ordinal = 3)
  18.     @BitPos(offset = 112, size = 1)
  19.     public int sex;
  20.     /**
  21.      * 年龄,最大127,7Bit
  22.      */
  23.     @JSONField(ordinal = 4)
  24.     @BitPos(offset = 113, size=7)
  25.     public int age;
  26.     /**
  27.      * 身高,最大2^10-1=1023cm,10Bit
  28.      */
  29.     @JSONField(ordinal = 5)
  30.     @BitPos(offset = 120, size = 10)
  31.     public int height;
  32.     /**
  33.      * 体重,最大2^10-1=1023kg,10Bit
  34.      */
  35.     @JSONField(ordinal = 6)
  36.     @BitPos(offset = 130, size = 10)
  37.     public int weight;
  38.     /**
  39.      * 多少个月的薪水,最大2^4-1=15个月薪,4Bit
  40.      */
  41.     @JSONField(ordinal = 7)
  42.     @BitPos(offset = 140, size=4)
  43.     public int monthSalary;
  44.     /**
  45.      * 地址:20字节,160bit
  46.      */
  47.     @JSONField(ordinal = 8)
  48.     @BitPos(offset = 144, size = 160)
  49.     public String address;
  50. }
复制代码
  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target(ElementType.FIELD)
  3. public @interface BitPos {
  4.     /**
  5.      * 位置(占总长度的位置)
  6.      */
  7.     int offset() default  -1;
  8.     /**
  9.      * 长度(多少bit)
  10.      */
  11.     int size() default  -1;
  12. }
复制代码
2. 工具类
[code]/** * 对象转位字节(整型实现按bit写入,字符串则按字节写入) * * 时间: 2024/1/23 11:12 */public class ObjToBitBytesUtil {    public static void main(String[] args) throws IllegalAccessException, UnsupportedEncodingException {        User user = new User();        user.id = 10001;        user.name = "张三";        user.sex = 0;        user.age = 18;        user.height = 170;        user.weight = 50;        user.monthSalary = 13;        user.address = "浙江杭州西湖";        System.out.println("原始对象:");        System.out.println(JSON.toJSONString(user, SerializerFeature.WriteNullStringAsEmpty));        //对象写成字节数组        byte[] bytes = writeObjToBitBytes(user, 38);        System.out.println("对象的字节数组16进制表示:");        printHex(bytes);        //字节数组转成对象        User readUser = readBitBytesToObj(bytes);        System.out.println("字节数组转换成的对象:");        System.out.println(JSON.toJSONString(readUser,SerializerFeature.WriteNullStringAsEmpty));    }    private static User readBitBytesToObj(byte[] bytes) throws IllegalAccessException, UnsupportedEncodingException {        User user = new User();        Field[] fields = user.getClass().getFields();        for (Field field : fields) {            BitPos bitPos = field.getAnnotation(BitPos.class);            Object val = readField(bytes, field, bitPos.offset(), bitPos.size());            field.set(user,val);        }        return user;    }    private static Object readField(byte[] buffer, Field field, int offset, int size) throws UnsupportedEncodingException {        Object val = null;       if(field.getType().equals(int.class) || field.getType().equals(Integer.class)){           // 整型,按位读取           int valInt = 0;           //起始缓存位置(第几个字节,从0开始)           int startBufferIndex = offset / 8;           //起始字节已经占用了多少bit           int startByteUsedBit = offset % 8;           int startByteRemainBit = 8 - startByteUsedBit;           //结束缓存位置(第几个字节)           int endBufferIndex = (offset + size - 1) / 8;           int endByteUseBit = ((offset + size - 1) % 8)+1;           // 缓存间隔位置(缓存起止位置之间的间隔字节数)           int gapByteCount = endBufferIndex - startBufferIndex - 1;           // 1. 读取起始字节(读高位)           byte lowerByte = buffer[startBufferIndex];           lowerByte = (byte) (lowerByte >>> startByteUsedBit);           int mask = (1  0) {               for (int i = 0; i < gapByteCount; i++) {                   int leftMove = startByteRemainBit + (i * 8);                   byte b = buffer[startBufferIndex+(i+1)];                   valInt |= (b  startBufferIndex) {               byte b = buffer[endBufferIndex];               int leftMove = startByteRemainBit + gapByteCount * 8;               mask = (1  startBufferIndex) {                int rightMove = startByteRemainBit + gapByteCount * 8;                mask = (1 > rightMove) & mask);            }        } else {            // 字符串直接按字节写入            byte[] bytes = val.toString().getBytes("utf-8");            int actualByteCount = bytes.length;            int startBufferIndex = offset / 8;            int endBufferIndex = startBufferIndex + size/8-1;            int byteIndex = 0;            for(int i = startBufferIndex; i




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4