java对象转成byte数组的3种方法

2025-05-29 0 26

java对象转成byte数组,在使用netty进行通信协议传输的场景中是非常常见的。比如,协议有一些定好的协议头、classid,messageid等等信息,还有一个关键的内容是payload。不同的协议内容都会放到payload中,而这个payload往往就是一个byte数组

那么,如何方便的将一个java对象构造成一个byte数组呢?

1 bytebuf填充

我们以下面这个对象举例:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29
public class ugvdata implements serializible{

private static final long serialversionuid = -219988432063763456l;

//状态码

byte status;

//当前gps经度

float longitude;

//当前gps纬度

float latitude;

//行驶速度 单位是 m/s,带一个小数点

float speed;

//当前电量百分比

short batterypercentage;

//任务编号

long quest;

public byte[] tobytearray() {

bytebuf buf = unpooled.buffer(32);

buf.writebyte(this.getstatus());

buf.writefloat(getlongitude());

buf.writefloat(getlatitude());

buf.writefloat(getspeed());

buf.writeshort(getbatterypercentage());

buf.writelong(getquest());

return buf.array();

}

//省略get set

}

那么只需要new出一个上面的对象,调用其tobytearray方法,即可将这个对象转成byte数组

2 巧用json

我们都知道,字符串是可以转成byte数组的。将一个对象转成json字符串也很容易,直接使用fastjson就可以了。如果对fastjson使用有问题的,可以看我的另一篇博客json.parseobject 和 json.tojsonstring 实例

?

1
json.tojsonstring(ugvdata).getbytes()

3 反射的方式

第一种方法的缺点在于,每一个类都要这么写一个tobytearray方法。如果类多了是非常麻烦的。有什么方便的方法吗?当然是有的,利用反射的方式(只会在第一次反射,后面会做本地缓存,所以性能开销不大)。需要在一个文件夹下添加下面五个类

1.codecable

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37
import com.fasterxml.jackson.annotation.jsonignore;

import com.google.common.collect.lists;

import lombok.data;

import java.lang.reflect.field;

import java.util.collections;

import java.util.comparator;

import java.util.list;

@data

public abstract class codecable {

public static list<fieldwrapper> resolvefileldwrapperlist(class clazz){

field[] fields = clazz.getdeclaredfields();

list<fieldwrapper> fieldwrapperlist = lists.newarraylist();

for (field field : fields) {

codecproprety codecproprety = field.getannotation(codecproprety.class);

if (codecproprety == null) {

continue;

}

fieldwrapper fw = new fieldwrapper(field, codecproprety);

fieldwrapperlist.add(fw);

}

collections.sort(fieldwrapperlist, new comparator<fieldwrapper>() {

@override

public int compare(fieldwrapper o1, fieldwrapper o2) {

return o1.getcodecproprety().order() - o2.getcodecproprety().order();

}

});

return fieldwrapperlist;

}

@jsonignore

public abstract list<fieldwrapper> getfieldwrapperlist();

}

2.codecproprety

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20
import java.lang.annotation.elementtype;

import java.lang.annotation.retention;

import java.lang.annotation.retentionpolicy;

import java.lang.annotation.target;

@retention(retentionpolicy.runtime)

@target({elementtype.field})

public @interface codecproprety {

/**

* 属性顺序

* @return

*/

int order();

/**

* 数据长度。解码时用,除了简单数据类型之外才起作用(如:string)。

* @return

*/

int length() default 0;

}

3.fieldwrapper

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16
import lombok.allargsconstructor;

import lombok.data;

import java.lang.reflect.field;

@data

@allargsconstructor

public class fieldwrapper {

/**

* 上下行数据属性

*/

private field field;

/**

* 上下行数据属性上的注解

*/

private codecproprety codecproprety;

}

4.payloaddecoder

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88
import io.netty.buffer.bytebuf;

import io.netty.buffer.unpooled;

import java.lang.reflect.field;

import java.lang.reflect.method;

import java.nio.charset.charset;

import java.util.list;

public class payloaddecoder {

public static <t extends codecable> t resolve(byte[] src, class<t> clazz) {

t instance = null;

try {

instance = clazz.newinstance();

} catch (exception e) {

throw new runtimeexception("实例化类失败", e);

}

list<fieldwrapper> fieldwrapperlist = instance.getfieldwrapperlist();

bytebuf buffer = unpooled.buffer().writebytes(src);

for (fieldwrapper fieldwrapper : fieldwrapperlist) {

filldata(fieldwrapper, instance, buffer);

}

return instance;

}

private static void filldata(fieldwrapper fieldwrapper, object instance, bytebuf buffer) {

field field = fieldwrapper.getfield();

field.setaccessible(true);

string typename = field.gettype().getname();

try {

switch (typename) {

case "java.lang.boolean":

case "boolean":

boolean b = buffer.readboolean();

field.set(instance, b);

break;

case "java.lang.character":

case "char":

charsequence charsequence = buffer.readcharsequence(fieldwrapper.getcodecproprety().length(), charset.forname("utf-8"));

field.set(instance, charsequence);

break;

case "java.lang.byte":

case "byte":

byte b1 = buffer.readbyte();

field.set(instance, b1);

break;

case "java.lang.short":

case "short":

short readshort = buffer.readshort();

field.set(instance, readshort);

break;

case "java.lang.integer":

case "int":

int readint = buffer.readint();

field.set(instance, readint);

break;

case "java.lang.long":

case "long":

long l = buffer.readlong();

field.set(instance, l);

break;

case "java.lang.float":

case "float":

float readfloat = buffer.readfloat();

field.set(instance, readfloat);

break;

case "java.lang.double":

case "double":

double readdouble = buffer.readdouble();

field.set(instance, readdouble);

break;

case "java.lang.string":

string readstring = buffer.readcharsequence(fieldwrapper.getcodecproprety().length(), charset.forname("utf-8")).tostring();

field.set(instance, readstring);

break;

default:

throw new runtimeexception(typename + "不支持,bug");

}

} catch (exception e) {

throw new runtimeexception(typename + "读取失败,field:" + field.getname(), e);

}

}

}

5.payloadencoder

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75
import io.netty.buffer.bytebuf;

import io.netty.buffer.unpooled;

import java.lang.reflect.field;

import java.lang.reflect.method;

import java.nio.charset.charset;

import java.util.list;

public class payloadencoder {

public static <t extends codecable> byte[] getpayload(t command) {

list<fieldwrapper> fieldwrapperlist = command.getfieldwrapperlist();

bytebuf buffer = unpooled.buffer();

fieldwrapperlist.foreach(fieldwrapper -> write2bytebuf(fieldwrapper, command, buffer));

return buffer.array();

}

/**

* 数据写入到bytebuf

*

* @param fieldwrapper

* @param instance

* @param buffer

*/

private static void write2bytebuf(fieldwrapper fieldwrapper, object instance, bytebuf buffer) {

field field = fieldwrapper.getfield();

string typename = field.gettype().getname();

field.setaccessible(true);

object value = null;

try {

value = field.get(instance);

} catch (illegalaccessexception e) {

new runtimeexception("反射获取值失败,filed:" + field.getname(), e);

}

switch (typename) {

case "java.lang.boolean":

case "boolean":

buffer.writeboolean((boolean) value);

break;

case "java.lang.character":

case "char":

buffer.writecharsequence((charsequence) value, charset.forname("utf-8"));

break;

case "java.lang.byte":

case "byte":

buffer.writebyte((byte) value);

break;

case "java.lang.short":

case "short":

buffer.writeshort((short) value);

break;

case "java.lang.integer":

case "int":

buffer.writeint((int) value);

break;

case "java.lang.long":

case "long":

buffer.writelong((long) value);

break;

case "java.lang.float":

case "float":

buffer.writefloat((float) value);

break;

case "java.lang.double":

case "double":

buffer.writedouble((double) value);

break;

case "java.lang.string":

buffer.writecharsequence((charsequence) value, charset.forname("utf-8"));

break;

default:

throw new runtimeexception(typename + "不支持,bug");

}

}

}

添加完上面五个类之后,使用也很简单,只需要如下所示,就可以把drivestartdata转成byte数组

?

1
payloadencoder.getpayload(drivestartdata)

4 总结

可能会有人问了,上面三种,明显第二种转json最简单,为什么还要用另外两种呢?

其实,第一种和第三种可以归为一类,都是把对象直接转成byte数组,下一层做解析的话,可以一个一个元素取;
第二种情况是把对象的json字符串转成byte数组,问题就在于,json字符串最开头是”{“,也就是转成的byte数组的第一位是”{“对应的数值

在使用中应该根据情况来,如果下一层做解析是直接取元素,对象少的话用第一种;对象多的话用第三种;
如果下一层做了排除掉json的一些格式的解析,就用第二种。

以上全部为本篇文章的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

原文链接:https://blog.csdn.net/antony9118/article/details/80713348

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 java对象转成byte数组的3种方法 https://www.kuaiidc.com/111281.html

相关文章

发表评论
暂无评论