官方網址: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); }