JavaStruct-java类序列化与c结构体交互

JavaStruct第三方库jar包下载地址(免费自取):

链接: https://pan.baidu.com/s/11AcJn8uk7yGlEEwEHa8_FA 
提取码: esgf

JavaStruct使用环境:

当与嵌入式设备和其他使用C结构的应用程序一起使用时,结构体类可用于大大简化Java
应用程序的网络协议代码。JavaStruct允许程序员将Java类视为c结构,而不是手动编码和
解码消息。
JavaStruct使用Java5或Java5以上版本jdk,将类和字段标记为结构体JavaStruct并不是第一
次提供类似结构的功能,Jean-Marie Dautelle的Javolution库也具有出色的结构实现。但
是,POJO方法不是首选JavaStruct,而不是在Javolution中使用特殊的类。

JavaStruct应用实现:

JavaStruct类用于打包java对象为字节格式,解包字节数据为Java序列化对象。Struct字段
具有顺序值,因为Java JVM规范不提供有关类成员顺序的任何信息。它们按其在Sun的实
现中的外观进行排序,但在其他JVM上有所不同。因此,每个Struct字段都必须提供一个排
序值。

@StructClass
公共类Foo {
	@StructField(order = 0)
	public byte b;
	@StructField(order = 1)
	public int i;
}

try {//将类打包为字节缓冲区
	Foo f = new Foo(); 
	fb =(byte)1; 
	fi = 1; 
	byte [] b = 	JavaStruct.pack(f);
	// Unpack it into an object
	Foo f2 = new Foo();
	JavaStruct.unpack(f2, b);
} catch(StructException e){}```
如果发生任何错误,Struct操作将抛出一个已检查的StructException。
Struct类也可以直接与Streams一起使用。请参考Photoshop ACB文件阅读器示例。

public void read(String acbFile){ 
	try { 
		FileInputStream fis = new FileInputStream(new File(acbFile)); 
		header = new ACBHeader(); 
		//ByteOrder.BIG_ENDIAN为大端排序,数据高位放在字节低位
		StructUnpacker up = JavaStruct.getUnpacker(fis, ByteOrder.BIG_ENDIAN); 
		up.readObject(header); 
		...

**原语**
使用原语。请注意,private和protected字段需要适当的getter和setter方法。Transient字段
将被自动排除。
@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);
	}
} 

**数组**
数组有一些先决条件。打开包装时,应在阵列中保留足够的空间。只有其长度使
ArrayLengthMarker在另一个字段中定义的数组(请参见下文)可以为空,它们在
拆包时会自动分配。除此之外,它们不能为null和未初始化。
@StructClass 
public class PublicPrimitiveArrays {
	@StructField(order = 0)
	public byte [] b = new byte [5];
	@StructField(order = 1)
	public char[] c = new byte[10];
	@StructField(order = 2)
	public short[] s;
	@StructField(order = 3)
	public int[] i;
}
**阵列长度标记**
数组长度标记对于其长度在anoher字段中定义的字段非常有用。考虑下面的例子。这是一
个特殊的String结构,其长度字段和其后的长度为16位字符。为了处理此问题,我们必须
将这些字符串表示为特殊的Struct类,比方说AStruct。长度字段应标注为
“ArrayLengthMarker”。这样,javastruct可以在打包和拆包操作期间在处理数组字段时自动
使用length字段中的值。
@StructClass public 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();
	}
} 

示例代码:

1.首先我们必须将这些字符串表示为特殊的Struct类AStruct。我们使用特殊的
ArrayLengthMarker批注。
@StructClass
public 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();
	}
}

@StructClass
public class ACBHeader {
	public static final short RGB = 0;
	public static final short CMYK = 2;
	public static final short LAB = 7;

//  Signature is always ASCII characters "8BCB"
	@StructField(order = 0)
	public byte[] signature = { '8', 'B', 'C', 'B' };

//	Photoshop 7 only opens files with a version of 1 (0x0001) 
	@StructField(order = 1)
	public short fileVersion;

//  Unique identifier..
	@StructField(order = 2)
	public short colorBookIdentifier;

	@StructField(order = 3)
	public AString title;

	@StructField(order = 4)
	public AString colorNamePrefix;

	@StructField(order = 5)
	public AString colorNamePostfix;

// Generally a copyright notice
	@StructField(order = 6)
	public AString description;

	@StructField(order = 7)
	public short colorCount;

//  Photoshop displays colors page by page. This field specifies the
//  maximum number of colors that can appear on a page.
	@StructField(order = 8)
	public short colorsPerPage;

	@StructField(order = 9)
	public short pageSelectorOffset;

//	RGB, CMYK or Lab
	@StructField(order = 10)
	public short colorSpaceID;
}

2.根据格式,颜色数据及其格式取决于colorSpaceID字段。它可以是RGB,CMYK或Lab。
因此,我们为每个颜色空间编写一个类。确切有颜色数据的“ colorCount”个数。
@StructClass
public class RGBColor {

	@StructField(order = 0)
	public AString name;

	@StructField(order = 1)
	public byte[] code = new byte[6];

	@StructField(order = 2)
	public byte red;

	@StructField(order = 3)
	public byte green;

	@StructField(order = 4)
	public byte blue;
}

@StructClass
public class LabColor {

	@StructField(order = 0)
	public AString name;

	@StructField(order = 1)
	public byte[] code = new byte[6];

	@StructField(order = 2)
	public byte lightness;

	@StructField(order = 3)
	public byte aChrom;

	@StructField(order = 4)
	public byte bChrom;
}

3.要读取和写入acb文件,我们使用FileStreams初始化StructPacker和StructUnpacker类。
之后,读取标题和颜色数据就非常简单了。
public class AdobeColorBook {
	ACBHeader header;
	RGBColor[] rgbColors = null;
	CMYKColor[] cmykColors = null;
	LabColor[] labColors = null;

	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);
			switch (header.ColorSpaceID) {
			case ACBHeader.RGB:
				rgbColors = new RGBColor[header.colorCount];
				for (int i = 0; i < header.colorCount; i++) {
					rgbColors[i] = new RGBColor();
					up.readObject(rgbColors[i]);
				}
				break;
			case ACBHeader.CMYK:
				cmykColors = new CMYKColor[header.colorCount];
				for (int i = 0; i < header.colorCount; i++) {
					cmykColors[i] = new CMYKColor();
					up.readObject(cmykColors[i]);
				}
				break;
			case ACBHeader.LAB:
				labColors = new LabColor[header.colorCount];
				for (int i = 0; i < header.colorCount; i++) {
					labColors[i] = new LabColor();
					up.readObject(labColors[i]);
				}
				break;
			default:
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (StructException e) {
			e.printStackTrace();
		}
	}

	public void write(String name) {
		try {
			FileOutputStream fo = new FileOutputStream(new File(name));
			StructPacker packer = JavaStruct.getPacker(fo, ByteOrder.BIG_ENDIAN);
			packer.writeObject(header);
			switch (header.ColorSpaceID) {
			case ACBHeader.RGB:
				for (RGBColor color : rgbColors) {
					packer.writeObject(color);
				}
				break;
			case ACBHeader.CMYK:
				for (CMYKColor color : cmykColors) {
					packer.writeObject(color);
				}
				break;
			case ACBHeader.LAB:
				for (LabColor color : labColors) {
					packer.writeObject(color);
				}
				break;
			default:
			}
			fo.close();
		} catch (StructException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public String toString() {
		String str = "";
		if (header != null) {
			str += header;
		}
		switch (header.ColorSpaceID) {
		case ACBHeader.RGB:
			for (RGBColor color : rgbColors) {
				str += color + "\n";
			}
			break;
		case ACBHeader.CMYK:
			for (CMYKColor color : cmykColors) {
				str += color + "\n";
			}
			break;
		case ACBHeader.LAB:
			for (LabColor color : labColors) {
				str += color + "\n";
			}
			break;
		}
		return str;
	}

	public static void main(String[] args) {
		AdobeColorBook anpaBook = new AdobeColorBook();
		anpaBook.read("ANPA Color.acb");
		anpaBook.write("ANPA_my_Color.acb");
		System.out.println(anpaBook);
	}
}
也可参考博客:https://blog.youkuaiyun.com/jazzsoldier/article/details/75570462
javastruct源码链接:https://github.com/dubrousky/javastruct
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值