javolution-core-java-6.1.0.jar 的使用
官方网址:http://javolution.org/apidocs/javolution/io/Struct.html
第一步:导包
第二步:创建继承的结构体
结构体定义如下所示:
public class SKJ_RECORD_INFO extends Struct { Unsigned8 infoID = new Unsigned8(); // 本数据结构标识,应为0x02 Unsigned8 infoVersion = new Unsigned8(); // 本书数据结构格式版本,应为0x00 Unsigned8 RecordLen = new Unsigned8(); // 交易记录的大小(字节数)。目前为80 Unsigned8 RecordVersion = new Unsigned8(); // 交易记录格式版本号,目前为0x30 Unsigned32 RecordMenSize = new Unsigned32(); // 交易记录存储空间总大小,单位:字节 Unsigned16 RecordCntMax = new Unsigned16(); // 交易记录存储从简最大的记录数量 Unsigned16 RecordCntTotal = new Unsigned16(); // 当前交易记录总数量,包括已采集的记录和未采集的记录 Unsigned16 RecordCntCollected = new Unsigned16(); // 当前已采集的记录数量 Unsigned16 RecordCntUnCollected = new Unsigned16(); // 当前尚未采集的记录数量 Unsigned16 RecotdCntFree = new Unsigned16(); // 当前空闲的记录存储控件数量 public void putData(byte[] data) { int structLen = this.size(); byte[] temp = new byte[structLen]; if (data.length >= structLen) { System.arraycopy(data, 0, temp, 0, structLen); } else { // 少于当前的结构的大小,以“0”来补充 System.arraycopy(data, 0, temp, 0, data.length); } ByteBuffer buff = ByteBuffer.wrap(temp); buff.order(this.byteOrder()); this.setByteBuffer(buff, 0); } // 一定要加上这个,不然会出现对齐的问题 @Override public boolean isPacked() { return true; } // 设置为小端数据 @Override public ByteOrder byteOrder() { return ByteOrder.LITTLE_ENDIAN; } }
测试:
public class SKJ_RECORD_INFOTest { @Before public void setUp() throws Exception { byte[] data = new byte[18]; for (int i = 0; i < data.length; i++) { data[i] = (byte) i; } SKJ_RECORD_INFO info = new SKJ_RECORD_INFO(); ByteBuffer b = ByteBuffer.wrap(data); b.order(ByteOrder.LITTLE_ENDIAN); info.setByteBuffer(b, 0); System.out.println(info.size()); System.out.println(info.infoID); System.out.println(info.RecotdCntFree); System.out.println("info.RecordMenSize:" + info.RecordMenSize); System.out.println(info.toString()); System.out.println("-----"); data[0] = 100; System.out.println(info.toString()); } @Test public void putData() throws Exception { } }
结果:
18
0
4368
info.RecordMenSize:117835012
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11
-----
64 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11
说明了一个问题:当前的info和字节数据data是关联在一起的了。data的数据改变,其对应indo的属性也会跟着改变。
public class SKJ_RECORD_INFOTest { @Before public void setUp() throws Exception { byte[] data = new byte[17]; for (int i = 0; i < data.length; i++) { data[i] = (byte) i; } SKJ_RECORD_INFO info = new SKJ_RECORD_INFO(); ByteBuffer b = ByteBuffer.wrap(data); b.order(ByteOrder.LITTLE_ENDIAN); info.setByteBuffer(b, 0); System.out.println(info.size()); System.out.println(info.infoID); System.out.println(info.RecotdCntFree); -- 报错了 System.out.println("info.RecordMenSize:" + info.RecordMenSize); System.out.println(info.toString()); System.out.println("-----"); data[0] = 100; System.out.println(info.toString()); } @Test public void putData() throws Exception { } }
结果:
18
0
java.lang.IndexOutOfBoundsException
at java.nio.Buffer.checkIndex(Buffer.java:546)
at java.nio.HeapByteBuffer.getShort(HeapByteBuffer.java:314)
at javolution.io.Struct$Unsigned16.get(Struct.java:1294)
at javolution.io.Struct$Unsigned16.toString(Struct.java:1309)
at java.lang.String.valueOf(String.java:2994)
at java.io.PrintStream.println(PrintStream.java:821)
at com.lanhetech.core.collectInfo.SKJ_RECORD_INFOTest.setUp(SKJ_RECORD_INFOTest.java:23)
……
说明了另一个问题:当前的data数据小于结构体info的大小时,info.setByteBuffer(b, 0);不会出错,但是引用到没有不够长度的数据时,就会出错了。
为了解决以上2个问题,新增一个putData()方法
public void putData(byte[] data) { int structLen = this.size(); byte[] temp = new byte[structLen]; if (data.length >= structLen) { System.arraycopy(data, 0, temp, 0, structLen); } else { // 少于当前的结构的大小,以“0”来补充 System.arraycopy(data, 0, temp, 0, data.length); } ByteBuffer buff = ByteBuffer.wrap(temp); buff.order(this.byteOrder()); this.setByteBuffer(buff, 0); }