Java 结构体之 JavaStruct 使用教程二 JavaStruct 用例分析
使用環(huán)境
前一篇在介紹 JavaStruct 類時(shí)指定了使用庫(kù)使用環(huán)境為 Java 5 及以上,也即開(kāi)發(fā)我們使用的 JDK 版本為1.5及以上就可以了。以下講解的用例可以直接將 code 直接粘貼到 java 的 main 函數(shù)中執(zhí)行就可以了,后面會(huì)給出測(cè)試用例和結(jié)果。
使用方法
JavaStruct 類用于打包和解包結(jié)構(gòu)體,也即使用方法為用該類的 pack 與 unpack 方法將定義的 struct 類轉(zhuǎn)換為字節(jié)流,或者將接收的字節(jié)流轉(zhuǎn)換為我們定義的 struct 類。如下所示為一個(gè)簡(jiǎn)單的用于檢查結(jié)構(gòu)體類的單元測(cè)試方法。結(jié)構(gòu)體成員變量前有一個(gè)排序數(shù)值,也即注解方式為 ?@StructField(order = 0)?這是因?yàn)?Java JVM 規(guī)范沒(méi)有任何有關(guān)類成員排序的說(shuō)明。使用此方式定義的結(jié)構(gòu)體成員會(huì)按照具體實(shí)現(xiàn)中使用的order進(jìn)行成員內(nèi)存排序,因此每一個(gè)結(jié)構(gòu)體成員必須提供一個(gè) order 數(shù)值。如下所示:
@StructClass public class Foo {@StructField(order = 0)public byte b;@StructField(order = 1)public int i;}注意,注解 @StructClass 以及 @StructField 不能省略。結(jié)構(gòu)體定義完成后,使用 pack 與 unpack 方法進(jìn)行類型轉(zhuǎn)換,如下所示為完整示例:
public class test {@StructClass public class Foo {@StructField(order = 0)public byte b;@StructField(order = 1)public int i;}public void TestFoo() {try { // Pack the class as a byte buffer Foo f = new Foo();f.b = (byte)1;f.i = 2; byte[] b = JavaStruct.pack(f);for (int i = 0; i < b.length; i++) {System.out.printf("b[%d]: %d\n", i, b[i]);}// Unpack it into an objectFoo f2 = new Foo();JavaStruct.unpack(f2, b);System.out.println("f2.b: " + f2.b);System.out.println("f2.i: " + f2.i);} catch(StructException e) { e.printStackTrace();} }public static void main(String args[]) {test t = new test();t.TestFoo();} }
直接觀察輸出結(jié)果:
從輸出結(jié)果可以看到,我們定義的結(jié)構(gòu)體被轉(zhuǎn)換成了 5 個(gè)字節(jié)的 byte 數(shù)組(int 占 4 個(gè)字節(jié)),可以看出來(lái) int 數(shù)據(jù)的地字節(jié)保存在了 byte 數(shù)組的高地址,可見(jiàn)使用 pack 打包時(shí)為大端排序。當(dāng)然,實(shí)際應(yīng)用時(shí)我們需要根據(jù)需求決定是使用大端還是小端排序。在 pack 與 unpack 方法指定就可以了,具體 pack 默認(rèn)為大端還是小端排序和處理器架構(gòu)及編譯器版本都有關(guān)系,因此要在項(xiàng)目應(yīng)用中以真實(shí)結(jié)果為準(zhǔn)。如改成小端:
byte[] b = JavaStruct.pack(f, ByteOrder.LITTLE_ENDIAN);?
如果運(yùn)行中發(fā)生錯(cuò)誤,結(jié)構(gòu)體操作會(huì)拋出 StructException 異常。
Struct 類也可以直接與 Stream 流一起使用。可以參考 Photoshop ACB 文件讀取?example,這里就不作詳細(xì)分析了。片段如下:
public void TestACB() {public void read(String acbFile) { try { FileInputStream fis = new FileInputStream(new File(acbFile)); header = new ACBHeader(); StructUnpacker up = JavaStruct.getUnpacker(fis, ByteOrder.BIG_ENDIAN); up.readObject(header); }}}
原型相關(guān)
對(duì)于使用原型,要注意對(duì)于 private 與 protected 成員需要用相應(yīng)的getter 與 setter 方法。Transient 成員會(huì)被自動(dòng)排除。如下所示:
@StructClass public class PublicPrimitives implements Serializable { @StructField(order = 0) public byte b;@StructField(order = 1)public char c;@StructField(order = 2)public short s;@StructField(order = 3)public int i;@StructField(order = 4)public long lo;@StructField(order = 5)protected float f;@StructField(order = 6)private double d;transient int blah;transient double foo;public float getF() {return f;}public void setF(float f) {this.f = f;}public double getD() {return d;}public void setD(double d) {this.d = d;}public boolean equals(Object o){PublicPrimitives other = (PublicPrimitives)o;return (this.b == other.b && this.c == other.c&& this.s == other.s&& this.i == other.i&& this.lo == other.lo&& this.f == other.f&& this.d == other.d);}}
數(shù)組相關(guān)
使用數(shù)組有一些先決條件。當(dāng)解包時(shí),數(shù)組一定要分配充足的空間。只有那些在另一個(gè)字段中使用ArrayLengthMarker(見(jiàn)下文) 定義長(zhǎng)度的數(shù)組可以為 null,這些數(shù)組在解包時(shí)會(huì)自動(dòng)分配空間。除此之外的數(shù)組定義不能為空和未初始化狀態(tài)。使用如下所示:
@StructClass public class PublicPrimitiveArrays { @StructField(order = 0) public byte[] b = new byte[5];@StructField(order = 1)public char[] c = new char[10];@StructField(order = 2)public short[] s;@StructField(order = 3)public int[] i;}
數(shù)組長(zhǎng)度標(biāo)記相關(guān)
數(shù)組長(zhǎng)度標(biāo)記(Array Length Markers)對(duì)于長(zhǎng)度在另一個(gè)字段中定義的字段十分有用。參見(jiàn)以下示例,這是個(gè)特殊的字符串結(jié)構(gòu)體,其有一個(gè)長(zhǎng)度字段以及緊跟其后的對(duì)應(yīng)這個(gè)長(zhǎng)度的 16 位字符。也即結(jié)構(gòu)為:
| Length | UTF-16 Characters ... |
為了處理這種情況,必須把這些字符串表示為一個(gè)特殊的結(jié)構(gòu)體類。長(zhǎng)度字段應(yīng)該注解為“ArrayLengthMarker”。通過(guò)這種方式,javastruct 可以在打包及解包操作中操作數(shù)組字段時(shí)自動(dòng)使用長(zhǎng)度字段中的值。示例如下:
@StructClasspublic class AString {@StructField (order = 0 )@ArrayLengthMarker (fieldName = "chars")public int length;@StructField (order = 1)public char[] chars;public AString(String content){this.length = content.length();this.chars = content.toCharArray();}}
關(guān)于 JavaStruct 應(yīng)用的文章系列,可以移步至如下鏈接:
1. 《Java 結(jié)構(gòu)體之 JavaStruct 使用教程<一> 初識(shí) JavaStruct》
2. 《Java 結(jié)構(gòu)體之 JavaStruct 使用教程<二> JavaStruct 用例分析》
3. 《Java 結(jié)構(gòu)體之 JavaStruct 使用教程<三> JavaStruct 數(shù)組進(jìn)階》
下載地址:http://download.csdn.net/download/jazzsoldier/9905451
有任何疑問(wèn)或使用問(wèn)題可以給我評(píng)論或者郵件哦,覺(jué)得有用就點(diǎn)贊吧~:-D
總結(jié)
以上是生活随笔為你收集整理的Java 结构体之 JavaStruct 使用教程二 JavaStruct 用例分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java764位_jdk7 64位下载
- 下一篇: Java 8 并发: 原子变量和 Con