java中字节数组对象的编码和解码
我有一个字节数组: [11,10,17,05,00,0a,01,02] 还有一节课:java中字节数组对象的编码和解码,java,arrays,types,Java,Arrays,Types,我有一个字节数组: [11,10,17,05,00,0a,01,02] 还有一节课: class abc{ short var1; // [11, 10] int var2; // [17, 05, 00, 0a] byte var3; // [01] byte var4; // [02] } 在python中有一个lib,您可以在其中提供一个字节
class abc{
short var1; // [11, 10]
int var2; // [17, 05, 00, 0a]
byte var3; // [01]
byte var4; // [02]
}
在python中有一个lib,您可以在其中提供一个字节数组,它将把它编码为类的一个对象(当然,结构需要事先定义)
我在java中寻找类似的东西,基本上就是我在寻找一种可以编码和解码字节数组的方法
[11,10,17,05,00,0a,01,02]=>(某些方法)=>对象abc:abc.getVar3()//根据上述结构,var3的值需要为1。
还有objectabc=>(一些方法)=>[11,10,17,05,00,0a,01,02]
我能想到的唯一解决办法是大量的if-else语句,即是否有更好的方法来做到这一点
我已经检查过了,它将整个类序列化为byte对象,但我只想编码数据,基本上在对象中注入数据,还从byte数组中的对象中检索数据。允许您从输入流中读取原语。注意以下方法:
readShort()
readInt()
readByte()
byte[] data = {0x11, 0x10, 0x17, 0x05, 0x00, 0x0a, 0x01, 0x02};
try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(data))) {
abc value = new abc();
value.var1 = in.readShort();
value.var2 = in.readInt();
value.var3 = in.readByte();
value.var4 = in.readByte();
}
import org.apache.commons.lang3.SerializationUtils;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
class Abc {
short var1; // [11, 10]
int var2; // [17, 05, 00, 0a]
byte var3; // [01]
byte var4; // [02]
public Map<String, Object> toMap() {
Map<String, Object> map = new HashMap<>();
map.put("var1", var1);
map.put("var2", var2);
map.put("var3", var3);
map.put("var4", var4);
return map;
}
public byte[] serializeMap() {
return SerializationUtils.serialize((Serializable) toMap());
}
public Map<String, Object> deSerializeMap(byte[] serializedObject) {
return SerializationUtils.deserialize(serializedObject);
}
public void setParams(Map<String, Object> deSerializedObject) {
this.var1 = (short) deSerializedObject.get("var1");
this.var2 = (int) deSerializedObject.get("var2");
this.var3 = (byte) deSerializedObject.get("var3");
this.var4 = (byte) deSerializedObject.get("var4");
}
}
public class Test2 {
public static void main(String[] args) {
Abc obj = new Abc();
obj.var1 = 10000;
obj.var2 = 500000;
obj.var3 = 2;
obj.var4 = 30;
Abc newObj = new Abc();
newObj.setParams(newObj.deSerializeMap(obj.serializeMap()));
System.out.printf("var1: %s\nvar2: %s\nvar3: %s\nvar4: %s\n", newObj.var1, newObj.var2, newObj.var3, newObj.var4);
}
}
有几种方法可以做到这一点。这里有一个简单的例子:
byte[] values = [11, 10, 17, 05, 00, 0a, 01, 02]; //WARNING: update 0a to the right value in java
类定义(java中的类名以大写字母开头):
因此,要创建新对象(对象为小写):
假设您已经查看了ApacheCommons中的序列化UTIL,您可以理解应该有某种基于类的对象作为任何序列化算法的输入 但是,您希望避免使用单独的专用类来存储和检索数据(如果我错了,请澄清我)。一种可能的解决方法是使用java中的内置类为您封装数据 例如,您可以将数据字段放在列表中(
ArrayList
),或者更好地放在映射中(HashMap
)。然后可以序列化映射对象,以便可以传递它。好的是,这些类已经内置到java中,因此您不需要仅仅为了序列化而创建单独的类
下面是一个示例代码:
byte[] data = {0x11, 0x10, 0x17, 0x05, 0x00, 0x0a, 0x01, 0x02};
try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(data))) {
abc value = new abc();
value.var1 = in.readShort();
value.var2 = in.readInt();
value.var3 = in.readByte();
value.var4 = in.readByte();
}
import org.apache.commons.lang3.SerializationUtils;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
class Abc {
short var1; // [11, 10]
int var2; // [17, 05, 00, 0a]
byte var3; // [01]
byte var4; // [02]
public Map<String, Object> toMap() {
Map<String, Object> map = new HashMap<>();
map.put("var1", var1);
map.put("var2", var2);
map.put("var3", var3);
map.put("var4", var4);
return map;
}
public byte[] serializeMap() {
return SerializationUtils.serialize((Serializable) toMap());
}
public Map<String, Object> deSerializeMap(byte[] serializedObject) {
return SerializationUtils.deserialize(serializedObject);
}
public void setParams(Map<String, Object> deSerializedObject) {
this.var1 = (short) deSerializedObject.get("var1");
this.var2 = (int) deSerializedObject.get("var2");
this.var3 = (byte) deSerializedObject.get("var3");
this.var4 = (byte) deSerializedObject.get("var4");
}
}
public class Test2 {
public static void main(String[] args) {
Abc obj = new Abc();
obj.var1 = 10000;
obj.var2 = 500000;
obj.var3 = 2;
obj.var4 = 30;
Abc newObj = new Abc();
newObj.setParams(newObj.deSerializeMap(obj.serializeMap()));
System.out.printf("var1: %s\nvar2: %s\nvar3: %s\nvar4: %s\n", newObj.var1, newObj.var2, newObj.var3, newObj.var4);
}
}
import org.apache.commons.lang3.SerializationUtils;
导入java.io.Serializable;
导入java.util.HashMap;
导入java.util.Map;
Abc班{
短var1;//[11,10]
int var2;/[17,05,00,0a]
字节var3;//[01]
字节var4;//[02]
公共地图toMap(){
Map Map=newhashmap();
地图放置(“var1”,var1);
地图放置(“var2”,var2);
地图放置(“var3”,var3);
地图放置(“var4”,var4);
返回图;
}
公共字节[]序列化映射(){
返回SerializationUtils.serialize((Serializable)toMap());
}
公共映射反序列化映射(字节[]serializedObject){
返回SerializationUtils.deserialize(SerializationObject);
}
public void setParams(映射反序列化对象){
this.var1=(短)反序列化对象.get(“var1”);
this.var2=(int)反序列化对象.get(“var2”);
this.var3=(字节)反序列化对象.get(“var3”);
this.var4=(字节)反序列化对象.get(“var4”);
}
}
公共类Test2{
公共静态void main(字符串[]args){
Abc obj=新Abc();
obj.var1=10000;
obj.var2=500000;
obj.var3=2;
obj.var4=30;
Abc newObj=新Abc();
newObj.setParams(newObj.deSerializeMap(obj.serializeMap());
System.out.printf(“var1:%s\nvar2:%s\nvar3:%s\nvar4:%s\n”,newObj.var1,newObj.var2,newObj.var3,newObj.var4);
}
}
正如您在这里看到的,我使用obj
创建值,然后序列化它,并newObj
反序列化并分配回变量
obj
可以属于一个类,您可以通过网络序列化和发送值,也可以在另一个对象上反序列化它们。这是可能的,因为HashMap已经内置到Java中
好的是,你们不需要在两个地方都上同样的课。只要这两个类都有上述变量(变量甚至不必具有相同的名称,只要类型匹配,这就可以工作),您就可以实现此解决方案。我建议使用Jackson并将其序列化为JSON。如果你想要一个你提到的自定义编码,那么你很可能需要弄脏你的手。您指定的编码不向后兼容,当情况发生变化时必然会中断。ObjectInputStream,ObjectOutputStream?这与我现在使用的解决方案类似我正在切片数组并创建所需的数据类型,然后将该值注入对象,我已经在映射的对象中存储了切片索引和数据类型以及映射到哪个变量,但我要寻找的是,既然我已经用它的适当数据类型定义了类,为什么我不能使用它并直接在该对象中注入值,类似于python中的
memmove
方法。@ooo这是不可能的,因为Java中的对象的内存布局很复杂。因此,您不知道var1是在var2之前还是之后出现;相反,您必须单独分配它们。@k314159有没有有效的方法可以这样做,假设您事先知道类结构,并且当您得到这个字节数组时,您可以在其中注入值。还有创建对象并将其转换为相同字节数组并发送的能力。(请注意,我不是说仅在对象中创建整个类的数据字节数组)有50多个唯一类,例如,我刚刚添加了4个变量,我正在寻找一些一般性的和懒惰的东西。请更新您的问题,因为这个评论非常相关。同样的事情只有使用java核心库才能实现吗?@ooo这是完全可能的。你已经看过你提到的答案了。已经有很多答案只使用内置的核心模块。再创造一个