简体   繁体   English

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

[英]How to map binary data in java class object?

Input data :hexadecimal 64 byte 输入数据:十六进制64字节

String binaryData="01000076183003104000800180f5010100010100000063000000630000006300000063000000000000000000820000000200b8010307010700640005e1cbe180";

Question is to read this binary data and set in class object Here is the model 问题是读取此二进制数据并设置在类对象中,这是模型

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;
}

I am currently doing this way to set values in each fields. 我目前正在以这种方式在每个字段中设置值。

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]));

}

It is working fine. 一切正常。 But I want it to be generic. 但我希望它是通用的。 So instead of giving byte by byte value. 因此,而不是逐字节给出值。 I want to direct map it to class fields. 我想直接将其映射到类字段。

In .net we are doing the marshalling for same feature that I need. 在.net中,我们正在对所需的相同功能进行编组。 Here is the example 这是例子

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));

}

To convert binary data, a byte[] to a class with fields, there is no memory template to shift the data in. A good solution is using a ByteBuffer , either on a byte array or InputStream. 要将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());
}

There exist other solutions, like using reflection, which is inefficient. 还有其他解决方案,例如使用反射,效率很低。

I used little endian byte order here, default in java is big endian. 我在这里使用了小端字节顺序,java中的默认值是大端字节。

There is the ObjectOutputStream, Serializable, persistence using serialisation. 有ObjectOutputStream,Serializable,使用序列化的持久性。 It stores class data too, so is not the language agnostic format you desire. 它还存储类数据,因此不是您想要的语言不可知格式。

While developing with a ByteBuffer is makes sense to check the read position. 使用ByteBuffer进行开发时,检查读取位置很有意义。

If you are interested in XML persistence, JAXB with annotations offers a nice reflection based way, without need of handling every field. 如果您对XML持久性感兴趣,那么带有批注的JAXB提供了一种基于反射的不错的方式,而无需处理每个字段。

A remark: Type[] variable is the preferred notation; 备注: Type[] variable是首选表示法; Type var[] was initially added to java to be compatible with C/C++. 最初将Type var[]添加到java中以与C / C ++兼容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM