如何在Java类对象中映射二进制数据?

时间:2019-02-26 08:12:06

标签: java

输入数据:十六进制64字节

String binaryData="01000076183003104000800180f5010100010100000063000000630000006300000063000000000000000000820000000200b8010307010700640005e1cbe180";

问题是要读取此二进制数据并设置在类对象中 这是模型

public class Transaction_PLUSale {


    public byte opcode;
    public byte[] code=new byte[7];

    public  byte flag1;
    public  byte flag2;
    public byte flag3;
    public byte flag4;
    public byte flag5;
    public short deptnum;
    public byte multi_sell_unit;
    public byte return_type;
    public byte tax_pointer;
    public int qty;
    public int price;
    public int amount;
    public int no_tax_price;
    public int no_tax_amount;
    public int return_surcharge_percent;
    public byte product_code;
    public byte flags;
    public TransactionTail tail;
}

我目前正在这种方式在每个字段中设置值。

String hexArray[]=  binaryData.split("(?<=\\G..)");
public static void readPLUSalesData(String hexArray[]) {
        Transaction_PLUSale pluSale=new Transaction_PLUSale();
        pluSale.setOpcode(Byte.valueOf(hexArray[0]));

        byte arr[]=new byte[7];
        for(int i=1;i<=7;i++) {
            arr[i-1]=Byte.valueOf(hexArray[i]);
        }
        pluSale.setCode(arr);
        pluSale.setFlag1(Byte.valueOf(hexArray[8]));
        pluSale.setFlag2(Byte.valueOf(hexArray[9]));
        pluSale.setFlag3(Byte.valueOf(hexArray[10]));
        pluSale.setFlag4(Byte.valueOf(hexArray[11]));
        pluSale.setFlag5(Byte.valueOf(hexArray[12]));
        pluSale.setDeptnum((short)Integer.parseInt((hexArray[14]+hexArray[13]),16));
        pluSale.setMulti_sell_unit(Byte.valueOf(hexArray[15]));
        pluSale.setReturn_type(Byte.valueOf(hexArray[16]));;
        pluSale.setTax_pointer(Byte.valueOf(hexArray[17]));
        pluSale.setQty(Integer.parseInt((hexArray[21]+hexArray[20]+hexArray[19]+hexArray[18]),16));
        pluSale.setPrice(Integer.parseInt((hexArray[25]+hexArray[24]+hexArray[23]+hexArray[22]),16));
        pluSale.setAmount(Integer.parseInt((hexArray[29]+hexArray[28]+hexArray[27]+hexArray[26]),16));
        pluSale.setNo_tax_price(Integer.parseInt((hexArray[33]+hexArray[32]+hexArray[31]+hexArray[30]),16));
        pluSale.setNo_tax_amount(Integer.parseInt((hexArray[37]+hexArray[36]+hexArray[35]+hexArray[34]),16));
        pluSale.setReturn_surcharge_percent(Integer.parseInt((hexArray[41]+hexArray[40]+hexArray[39]+hexArray[38]),16));
        pluSale.setProduct_code(Byte.valueOf(hexArray[42]));
        pluSale.setFlags(Byte.valueOf(hexArray[43]));

}

工作正常。但我希望它是通用的。因此,而不是逐字节给出值。我想直接将其映射到类字段。

在.net中,我们正在对所需的相同功能进行编组。 这是示例

foreach (KeyValuePair<string, byte[]> s in t)
                    {
//byte array consist of bytes of the above hexadecimal string.
                        Ticket ticket = new Ticket();

                        int count = Marshal.SizeOf(typeof(Transaction_Coupon));
                        MemoryStream ms = new MemoryStream(s.Value);
                        byte[] readBuffer = new byte[count];
                        BinaryReader br = new BinaryReader(ms);
                        readBuffer = br.ReadBytes(count);
                        GCHandle handle = GCHandle.Alloc(readBuffer, GCHandleType.Pinned);

//here we are mapping byte data to each field
                        Transaction_PLUSale t_plusale = (Transaction_PLUSale)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Transaction_PLUSale));

}

1 个答案:

答案 0 :(得分:0)

要将byte[]二进制数据转换为具有字段的类,没有内存模板可将数据移入。一个好的解决方案是在字节数组或InputStream上使用ByteBuffer

public static void readPLUSalesData(String[] hexArray) {
    byte[] bytes = new byte[hexArray.length];
    for (int i = 0; i < bytes.length; ++i) {
         bytes[i] = Byte.parseByte(hexArray[i], 16);
    }

    ByteBuffer buf = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN;

    Transaction_PLUSale pluSale=new Transaction_PLUSale();
    pluSale.setOpcode(buf.get());

    byte[] arr[] = new byte[7];
    buf.get(arr);
    pluSale.setCode(arr);
    pluSale.setFlag1(buf.get());
    pluSale.setFlag2(buf.get());
    pluSale.setFlag3(buf.get());
    pluSale.setFlag4(buf.get());
    pluSale.setFlag5(buf.get());
    pluSale.setDeptnum(buf.getShort());
    pluSale.setMulti_sell_unit(buf.get());
    pluSale.setReturn_type(buf.get());
    pluSale.setTax_pointer(buf.get());
    pluSale.setQty(buf.getInt());
    pluSale.setPrice(buf.getInt());
    pluSale.setAmount(buf.getInt());
    pluSale.setNo_tax_price(buf.getInt());
    pluSale.setNo_tax_amount(buf.getInt());
    pluSale.setReturn_surcharge_percent(buf.getInt());
    pluSale.setProduct_code(buf.get());
    pluSale.setFlags(buf.get());
}

还有其他解决方案,例如使用反射,效率不高。

我在这里使用了小尾数字节顺序,java中的默认值是大尾数。

有ObjectOutputStream,可序列化,使用序列化的持久性。 它也存储类数据,因此不是您想要的与语言无关的格式。

使用ByteBuffer进行开发时,可以检查读取位置。

如果您对XML持久性感兴趣,带有批注的JAXB提供了一种不错的基于反射的方式,而无需处理每个字段。

备注:Type[] variable是首选符号; Type var[]最初是添加到Java中以与C / C ++兼容的。