JavaStruct

一、JavaStruct介绍和入门

资源:javastruct.jar:n967(好多地方多需要积分下载,这块儿直接上货,感觉好用的评论给我扣个“好”)

javastruct

A library to treat java objects as C structs.

一个将java对象视为C结构的库


 


 


 

HowToUseJavaStruct 

This page explains how to use JavaStruct library.
Featured, Phase-Implementation

Updated Feb 4, 2010 by [email protected]

201024日更新mda…@gmail.com

Introduction

Struct classes can be used to greatly simplfy network protocol codes of Java applications when working with embedded devices and other applications which uses C style structs.

Struct类可用于大大simplfy网络协议规范的Java应用程序在处理嵌入式设备和其他应用程序使用C风格的结构

Instead of manually encoding and decoding messages, JavaStruct allows programmers to treat java classes as c structs.

JavaStruct代替了手工编码和解码消息,允许程序员把java类当作c结构来对待。

JavaStruct uses Java 5 annotations to mark Classes and fields as structs. JavaStruct is not the first attempt to provide struct like functionality, Jean-Marie Dautelle's Javolution library also has an excellent struct implementation. But instead of using special classes in Javolution, POJO approach is preferred JavaStruct.

JavaStruct使用Java 5注释将类和字段标记为结构。JavaStruct不是第一个尝试提供结构和功能一样,-玛丽•Dautelle Javolution图书馆也有一个优秀的结构实现。而是Javolution使用特殊类的POJO方法是首选JavaStruct

General usage

JavaStruct façade class is used to pack and unpack struct classes. Below is a simple unit test method for checking a struct class. Struct fields hasan order value, because Java JVM specification does not tell anything about order of the class members. They are ordered as their appearance in Sun's implementation but it differs on other JVM's. So every Struct field has to supply an order value.

JavaStruct facade类用于打包和打开struct类。下面是检查struct类的简单单元测试方法。Struct字段hasan order value,因为Java JVM规范没有告诉任何类成员的顺序。它们被命令在Sun的实现中出现,但与其他JVM不同。因此每个Struct字段都必须提供一个order值。

@StructClass
publicclassFoo{

   
@StructField(order =0)
   
publicbyte b;

   
@StructField(order =1)
   
publicint i;
}

try{
   
// Pack the class as a byte buffer将类打包为一个字节缓冲区
   
Foo f =newFoo(); //媒体处理器
    f
.b =(byte)1;
    f
.i =1;
   
byte[] b =JavaStruct.pack(f);
   
   
// Unpack it into an object把它解压到一个对象中
   
Foo f2 =newFoo();
   
JavaStruct.unpack(f2, b);
}
catch(StructException e){
}

Struct operations throws a checked StructException if anything goes wrong.

如果出现问题,Struct操作会抛出一个检查的结构异常。

Struct classes can be used with Streams directly too. Please refer to Photoshop ACB file reader

Struct类也可以直接使用流。请参阅Photoshop ACB文件阅读器

example.

publicvoid read(String acbFile){
   
try{
       
FileInputStream fis =newFileInputStream(newFile(acbFile));
        header
=newACBHeader();
       
StructUnpacker up =JavaStruct.getUnpacker(fis,ByteOrder.BIG_ENDIAN);
        up
.readObject(header);
...

Primitives

基本体

Using primitives. Note that private and protected fields requires appropriate getter and setter methods. Transient fields are automatically excluded.

使用原语。注意,私有和受保护的字段需要适当的gettersetter方法。瞬态字段被自动排除。

@StructClass
publicclassPublicPrimitivesimplementsSerializable{
       
@StructField(order =0)
       
publicbyte b;

       
@StructField(order =1)
       
publicchar c;

       
@StructField(order =2)
       
publicshort s;

       
@StructField(order =3)
       
publicint i;

       
@StructField(order =4)
       
publiclong lo;

       
@StructField(order =5)
       
protectedfloat f;

       
@StructField(order =6)
       
privatedouble d;

       
transientint blah;// transient短暂的
       
transientdouble foo;


       
publicfloat getF(){
               
return f;
       
}

       
publicvoid setF(float f){
               
this.f = f;
       
}

       
publicdouble getD(){
               
return d;
       
}

       
publicvoid setD(double d){
               
this.d = d;
       
}

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

Arrays

数组

Arrays have some prerequisites. When unpacking, sufficent space should be reserved in the array. Only arrays, whose lengths are defined in another field using ArrayLengthMarker (see below section) can be null, they are automatically allocated while unpacking. Other than that they can not be null and uninitialized.

数组有一些先决条件。当未包装的时候,应该在数组中保留足够的空间。只有数组,在另一个字段中使用ArrayLengthMarker(见下部分)的长度定义为空,可以在不打包时自动分配。除此之外,它们不能为零和未初始化。

@StructClass
publicclassPublicPrimitiveArrays{//Primitive  原始的
       
@StructField(order =0)
       
publicbyte[] b =newbyte[5];

       
@StructField(order =1)
       
publicchar[] c =newbyte[10];

       
@StructField(order =2)
       
publicshort[] s;

       
@StructField(order =3)
       
publicint[] i;
}

Array Length Markers

数组长度的标记

Array length markers are very useful for the fields whose legth is defined in anoher field. consider the following example. This is a special String struct which has a length fields and length number of 16 bit characters following it.

数组长度的标记对于那些在她的字段中定义了legth的字段非常有用。考虑下面的例子。这是一个特殊的字符串结构体,它有一个长度字段和16位字符的长度。

  +--------+-----------------------//----------------------------------------+
 
|Length| UTF-16Characters     \\                                        |
 
+--------+-----------------------//----------------------------------------+

In order to process this, we have to represent these strings as a special Struct class, lets say AStruct. The length field should be annotated as "ArrayLengthMarker". This way javastruct can automatically use the value in length field while processing the array field during packing and unpacking operations.

为了处理这个问题,我们必须将这些字符串表示为一个特殊的Struct类,比如AStruct。字段长度应标注为“ArrayLengthMarker”。通过这种方式,javastruct可以自动在长度字段中使用值,同时在包装和解压缩操作期间处理数组字段。

@StructClass
publicclassAString{
       
       
@StructField(order =0)
       
@ArrayLengthMarker(fieldName ="chars")
       
publicint length;
       
       
@StructField(order =1)
       
publicchar[] chars;
       
       
publicAString(String content){
                
this.length = content.length();
               
this.chars = content.toCharArray();
       
}
...
}

 

Comment by [email protected], Dec 19, 2011Thanks for this example. But how toread a struct from buffer ?

发表评论skossent…@gmail.com,20111219,谢谢你的这个例子。但是如何从缓冲区中读取结构体呢?

Comment by [email protected], Feb 10, 2012Is there anything special thatneeds to be done to allow this to work with 2D arrays?

评论cory.d…@gmail.com,210,2012有什么特殊需要做这允许使用二维数组吗?

Here is the object that I am trying to pack

这是我想要打包的对象

@StructClass
publicclassSEND_DATA_STRUCTURE
{
   
@StructField(order =0)
   
publicfloatgyro_offset[]=newfloat[3];
  
   
@StructField(order =1)
   
publicfloataccel_offset[]=newfloat[3];
   
   
@StructField(order =2)
   
publicfloatMagCalRotationMat[][]=newfloat[3][3];
   
   
@StructField(order =3)
   
publicfloatMagCalScaleMat[][]=newfloat[3][3];
   
   
@StructField(order =4)
   
publicfloatMagCalShiftMat[][]=newfloat[1][3];

} 
 

Here is the code I'm using to pack it:

这是我使用的代码包

byte[] b;
SEND_DATA_STRUCTURE txData
=newSEND_DATA_STRUCTURE();
b
=JavaStruct.pack(txData,ByteOrder.LITTLE_ENDIAN);

and this is the runtime error that I get:struct.StructException?: struct.StructException?: No struct Annotation found for [F

If I get rid of the 2D arrays, I don't get that exception.

这是我得到的运行时错误:structexception ?:struct.StructException ?(F)没有找到任何struct注释

如果我去掉2D数组,我就不会得到那个例外。

Comment by [email protected], Feb 6, 2013What if thereare multiple fields in the struct that can be variable length. How do we useArrayLengthMarker? in that situation? It seems like it can only be used for onechunk of data since it requires the constructor...

发表评论sender.e…@gmail.com,201326,如果有多个字段结构可变长度。我们如何使用ArrayLengthMarker?在那种情况下?它似乎只能用于一个数据块,因为它需要构造函数。

二、实战

java实体类:

package JKWR.POJO;

import java.util.Arrays;

import struct.StructClass;
import struct.StructField;

@StructClass
public class NETPRO_INFO {
	@StructField(order = 0)
	int probe_id;
	@StructField(order = 1)
	int pad;
	@StructField(order = 2)
	int cmd_type;
	@StructField(order = 3)
	int cmd_length;
	@StructField(order = 4)
	byte[] ip = new byte[4];
	@StructField(order = 5)
	byte[] mask = new byte[4];
	@StructField(order = 6)
	byte[] gateway = new byte[4];
	@StructField(order = 7)
	byte[] dns = new byte[4];
	@StructField(order = 8)
	byte[] manage_center_ip = new byte[4];
	@StructField(order = 9)
	int manage_center_port;
	@StructField(order = 10)
	byte[] redis_ip = new byte[4];
	@StructField(order = 11)
	int redis_port;
	@StructField(order = 12)
	byte[] analyze_center_ip = new byte[4];
	@StructField(order = 13)
	int analyze_center_port;
	@StructField(order = 14)
	byte[] syslog_first_ip = new byte[4];
	@StructField(order = 15)
	int syslog_first_port;
	@StructField(order = 16)
	byte[] syslog_second_ip = new byte[4];
	@StructField(order = 17)
	int syslog_second_port;
	@StructField(order = 18)
	byte[] kafka_first_ip = new byte[4];
	@StructField(order = 19)
	int kafka_first_port;
	@StructField(order = 20)
	byte[] kafka_second_ip = new byte[4];
	@StructField(order = 21)
	int kafka_second_port;
	@StructField(order = 22)
	int run_time;
	@StructField(order = 23)
	int active_time;
	@StructField(order = 24)
	int cpu;
	@StructField(order = 25)
	int cpu_used;
	@StructField(order = 26)
	int mem;
	@StructField(order = 27)
	int mem_used;
	@StructField(order = 28)
	int disk;
	@StructField(order = 29)
	int disk_used;
	@StructField(order = 30)
	int port_number;
	@StructField(order = 31)
	int output_mode;
	@StructField(order = 32)
	byte[] probe_seq = new byte[16];
	@StructField(order = 33)
	int[] port = new int[20];
	@StructField(order = 34)
	int[] link_id = new int[20];
	public int getProbe_id() {
		return probe_id;
	}
	public void setProbe_id(int probe_id) {
		this.probe_id = probe_id;
	}
	public int getPad() {
		return pad;
	}
	public void setPad(int pad) {
		this.pad = pad;
	}
	public int getCmd_type() {
		return cmd_type;
	}
	public void setCmd_type(int cmd_type) {
		this.cmd_type = cmd_type;
	}
	public int getCmd_length() {
		return cmd_length;
	}
	public void setCmd_length(int cmd_length) {
		this.cmd_length = cmd_length;
	}
	public byte[] getIp() {
		return ip;
	}
	public void setIp(byte[] ip) {
		this.ip = ip;
	}
	public byte[] getMask() {
		return mask;
	}
	public void setMask(byte[] mask) {
		this.mask = mask;
	}
	public byte[] getGateway() {
		return gateway;
	}
	public void setGateway(byte[] gateway) {
		this.gateway = gateway;
	}
	public byte[] getDns() {
		return dns;
	}
	public void setDns(byte[] dns) {
		this.dns = dns;
	}
	public byte[] getManage_center_ip() {
		return manage_center_ip;
	}
	public void setManage_center_ip(byte[] manage_center_ip) {
		this.manage_center_ip = manage_center_ip;
	}
	public int getManage_center_port() {
		return manage_center_port;
	}
	public void setManage_center_port(int manage_center_port) {
		this.manage_center_port = manage_center_port;
	}
	public byte[] getRedis_ip() {
		return redis_ip;
	}
	public void setRedis_ip(byte[] redis_ip) {
		this.redis_ip = redis_ip;
	}
	public int getRedis_port() {
		return redis_port;
	}
	public void setRedis_port(int redis_port) {
		this.redis_port = redis_port;
	}
	public byte[] getAnalyze_center_ip() {
		return analyze_center_ip;
	}
	public void setAnalyze_center_ip(byte[] analyze_center_ip) {
		this.analyze_center_ip = analyze_center_ip;
	}
	public int getAnalyze_center_port() {
		return analyze_center_port;
	}
	public void setAnalyze_center_port(int analyze_center_port) {
		this.analyze_center_port = analyze_center_port;
	}
	public byte[] getSyslog_first_ip() {
		return syslog_first_ip;
	}
	public void setSyslog_first_ip(byte[] syslog_first_ip) {
		this.syslog_first_ip = syslog_first_ip;
	}
	public int getSyslog_first_port() {
		return syslog_first_port;
	}
	public void setSyslog_first_port(int syslog_first_port) {
		this.syslog_first_port = syslog_first_port;
	}
	public byte[] getSyslog_second_ip() {
		return syslog_second_ip;
	}
	public void setSyslog_second_ip(byte[] syslog_second_ip) {
		this.syslog_second_ip = syslog_second_ip;
	}
	public int getSyslog_second_port() {
		return syslog_second_port;
	}
	public void setSyslog_second_port(int syslog_second_port) {
		this.syslog_second_port = syslog_second_port;
	}
	public byte[] getKafka_first_ip() {
		return kafka_first_ip;
	}
	public void setKafka_first_ip(byte[] kafka_first_ip) {
		this.kafka_first_ip = kafka_first_ip;
	}
	public int getKafka_first_port() {
		return kafka_first_port;
	}
	public void setKafka_first_port(int kafka_first_port) {
		this.kafka_first_port = kafka_first_port;
	}
	public byte[] getKafka_second_ip() {
		return kafka_second_ip;
	}
	public void setKafka_second_ip(byte[] kafka_second_ip) {
		this.kafka_second_ip = kafka_second_ip;
	}
	public int getKafka_second_port() {
		return kafka_second_port;
	}
	public void setKafka_second_port(int kafka_second_port) {
		this.kafka_second_port = kafka_second_port;
	}
	public int getRun_time() {
		return run_time;
	}
	public void setRun_time(int run_time) {
		this.run_time = run_time;
	}
	public int getActive_time() {
		return active_time;
	}
	public void setActive_time(int active_time) {
		this.active_time = active_time;
	}
	public int getCpu() {
		return cpu;
	}
	public void setCpu(int cpu) {
		this.cpu = cpu;
	}
	public int getCpu_used() {
		return cpu_used;
	}
	public void setCpu_used(int cpu_used) {
		this.cpu_used = cpu_used;
	}
	public int getMem() {
		return mem;
	}
	public void setMem(int mem) {
		this.mem = mem;
	}
	public int getMem_used() {
		return mem_used;
	}
	public void setMem_used(int mem_used) {
		this.mem_used = mem_used;
	}
	public int getDisk() {
		return disk;
	}
	public void setDisk(int disk) {
		this.disk = disk;
	}
	public int getDisk_used() {
		return disk_used;
	}
	public void setDisk_used(int disk_used) {
		this.disk_used = disk_used;
	}
	public int getPort_number() {
		return port_number;
	}
	public void setPort_number(int port_number) {
		this.port_number = port_number;
	}
	public int getOutput_mode() {
		return output_mode;
	}
	public void setOutput_mode(int output_mode) {
		this.output_mode = output_mode;
	}
	public byte[] getProbe_seq() {
		return probe_seq;
	}
	public void setProbe_seq(byte[] probe_seq) {
		this.probe_seq = probe_seq;
	}
	public int[] getPort() {
		return port;
	}
	public void setPort(int[] port) {
		this.port = port;
	}
	public int[] getLink_id() {
		return link_id;
	}
	public void setLink_id(int[] link_id) {
		this.link_id = link_id;
	}
	@Override
	public String toString() {
		return "NETPRO_INFO [probe_id=" + probe_id + ", pad=" + pad
				+ ", cmd_type=" + cmd_type + ", cmd_length=" + cmd_length
				+ ", ip=" + Arrays.toString(ip) + ", mask="
				+ Arrays.toString(mask) + ", gateway="
				+ Arrays.toString(gateway) + ", dns=" + Arrays.toString(dns)
				+ ", manage_center_ip=" + Arrays.toString(manage_center_ip)
				+ ", manage_center_port=" + manage_center_port + ", redis_ip="
				+ Arrays.toString(redis_ip) + ", redis_port=" + redis_port
				+ ", analyze_center_ip=" + Arrays.toString(analyze_center_ip)
				+ ", analyze_center_port=" + analyze_center_port
				+ ", syslog_first_ip=" + Arrays.toString(syslog_first_ip)
				+ ", syslog_first_port=" + syslog_first_port
				+ ", syslog_second_ip=" + Arrays.toString(syslog_second_ip)
				+ ", syslog_second_port=" + syslog_second_port
				+ ", kafka_first_ip=" + Arrays.toString(kafka_first_ip)
				+ ", kafka_first_port=" + kafka_first_port
				+ ", kafka_second_ip=" + Arrays.toString(kafka_second_ip)
				+ ", kafka_second_port=" + kafka_second_port + ", run_time="
				+ run_time + ", active_time=" + active_time + ", cpu=" + cpu
				+ ", cpu_used=" + cpu_used + ", mem=" + mem + ", mem_used="
				+ mem_used + ", disk=" + disk + ", disk_used=" + disk_used
				+ ", port_number=" + port_number + ", output_mode="
				+ output_mode + ", probe_seq=" + Arrays.toString(probe_seq)
				+ ", port=" + Arrays.toString(port) + ", link_id="
				+ Arrays.toString(link_id) + "]";
	}
	
}

通过javaStruct进行java实体类和byte数组的转化:

        NETPRO_INFO netpro_INFO1 = new NETPRO_INFO();
        JavaStruct.unpack(netpro_INFO1, data2, ByteOrder.LITTLE_ENDIAN);
//      由于unpack函数不能将数组按照类的结构转换大小端,所以用pack来做这个工作。先将错误的对象转化为byte数组(按小端)
        byte[] pack = JavaStruct.pack(netpro_INFO1,ByteOrder.LITTLE_ENDIAN);
        NETPRO_INFO netpro_INFO = new NETPRO_INFO();
//      然后将按类结构小端排列的数组unpack成为真确的对象
        JavaStruct.unpack(netpro_INFO, pack);

猜你喜欢

转载自blog.csdn.net/tansuoliming/article/details/80240623