netty04-序列化反序列化

╰+哭是因爲堅強的太久メ 2022-05-31 04:50 408阅读 0赞

序列化协议基础

  • 基础类型int在内存中的原始序列化

  • 基于nio的序列化

  • 基于netty的序列化

int类型序列化

int类型序列化方式有两种

大端序列:先写高位,在写低位

小端序列:先写低位,在写高位

左边是高位 右边是低位

00000000 00000000 00000000 00001011 = 11

  1. /**
  2. * 将int数值转换为占四个字节的byte数组, 低位在前,高位在后
  3. */
  4. public static byte[] intToBytes(int value)
  5. {
  6. byte[] byteArray = new byte[4];
  7. // 最高位放在最后一个字节 ,也就是向右移动3个字节 = 24位
  8. byteArray[3] = (byte) ((value & 0xFF000000)>>3*8);// 最高位,放在字节数组最后
  9. byteArray[2] = (byte) ((value & 0x00FF0000)>>2*8);// 左边第二个字节
  10. byteArray[1] = (byte) ((value & 0x0000FF00)>>1*8);
  11. byteArray[0] = (byte) ((value & 0x000000FF)); // 最低位
  12. //[11,0,0,0]
  13. return byteArray;
  14. }

value & 0xFF000000解释:

00000000 00000000 00000000 00001011

& 11111111 00000000 00000000 00000000

= 00000000 00000000 00000000 00000000 = 0

int类型反序列化

  1. /**
  2. * byte数组转int; 低位在前,高位在后
  3. */
  4. public static int bytesToInt(byte[] byteArray) {
  5. return (byteArray[0]&0xFF)|
  6. ((byteArray[1]<<1*8) & 0xFF00)|
  7. ((byteArray[2]<<2*8) & 0xFF0000)|
  8. ((byteArray[3]<<3*8) & 0xFF000000);
  9. }

写个测试方法,代码如下:

  1. public static void main(String[] args) throws Exception {
  2. int a = 11;
  3. int b = 22;
  4. int c = 88;
  5. ByteArrayOutputStream os = new ByteArrayOutputStream();
  6. //os.write(a);// 为什么不用这个?
  7. os.write(intToBytes(a));
  8. os.write(intToBytes(b));
  9. os.write(intToBytes(c));
  10. byte[] byteArray = os.toByteArray();
  11. System.out.println(Arrays.toString(byteArray));
  12. ByteArrayInputStream is = new ByteArrayInputStream(byteArray);
  13. byte[] aBytes = new byte[4];
  14. byte[] bBytes = new byte[4];
  15. byte[] cBytes = new byte[4];
  16. is.read(aBytes);
  17. is.read(bBytes);
  18. is.read(cBytes);
  19. System.out.println("a: " + bytesToInt(aBytes));
  20. System.out.println("b: " + bytesToInt(bBytes));
  21. System.out.println("c: " + bytesToInt(cBytes));
  22. }

运行结果:

SouthEast

nio序列化反序列化

  1. public static void main(String[] args) {
  2. int a = 11;
  3. int b = 22;
  4. // 序列化
  5. ByteBuffer buffer = ByteBuffer.allocate(8);
  6. buffer.putInt(a);
  7. buffer.putInt(b);
  8. // buffer.putInt(2);
  9. byte[] array = buffer.array();
  10. System.out.println(Arrays.toString(buffer.array()));
  11. // 反序列化
  12. ByteBuffer bb = ByteBuffer.wrap(array);
  13. System.out.println("a: " + bb.getInt());
  14. System.out.println("b: " + bb.getInt());
  15. }

对比传统序列化可以看出简便很多,但是也有缺点就是ByteBuffer不是动态扩容的,默认是多少是不能增加的。即解决复杂的运算但是不支持扩容。有没有两者兼得的呢?netty。。。

netty序列化反序列化

  1. public static void main(String[] args) {
  2. ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
  3. buffer.writeInt(11);
  4. buffer.writeInt(22);
  5. buffer.writeLong(23);
  6. buffer.writeLong(23);
  7. // byte数组的大小由buffer中写指针的位置决定
  8. // 往ChannelBuffer中写数据的时候,这个写指针就会移动写的数据的长度
  9. byte[] bytes = new byte[buffer.writerIndex()];
  10. buffer.readBytes(bytes); // 序列化
  11. System.out.println(Arrays.toString(bytes));
  12. // 反序列化
  13. ChannelBuffer wrappedBuffer = ChannelBuffers.wrappedBuffer(bytes);
  14. System.out.println(wrappedBuffer.readInt());
  15. System.out.println(wrappedBuffer.readInt());
  16. }

对象序列化

Java原始对象序列化

ObjectInputStream,ObjectOutStream

  1. package com.hotpot.netty04.java;
  2. import java.io.ByteArrayInputStream;
  3. import java.io.ByteArrayOutputStream;
  4. import java.io.ObjectInputStream;
  5. import java.io.ObjectOutputStream;
  6. import java.util.ArrayList;
  7. import java.util.Arrays;
  8. import java.util.List;
  9. /**
  10. * 描述:java原始序列化
  11. * ObjectOutputStream 序列化
  12. * ObjectInputStream 反序列化
  13. * @author: myx
  14. * @date: 2018/2/7 0007
  15. * Copyright © 2018-ganinfo. All rights reserved.
  16. */
  17. public class JavaSeri {
  18. public static void main(String[] args) throws Exception{
  19. // 序列化
  20. byte[] result = serialize();
  21. System.out.println(Arrays.toString(result));
  22. // 反序列化
  23. SubscribeReq req = deserialize(result);
  24. System.out.println(req.getSubReqID());
  25. System.out.println(req.getUserName());
  26. System.out.println(req.getProductName());
  27. System.out.println(req.getAddressList().get(0));
  28. System.out.println(req.getAddressList().get(1));
  29. }
  30. // 序列化
  31. public static byte[] serialize() throws Exception{
  32. SubscribeReq req = new SubscribeReq();
  33. req.setSubReqID(1);
  34. req.setUserName("abc");
  35. req.setProductName("netty");
  36. List<String> addressList = new ArrayList<String>();
  37. addressList.add("北京");
  38. addressList.add("沧州");
  39. req.setAddressList(addressList);
  40. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  41. ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos);
  42. // 把SubscribeReq对象写入ByteArrayOutputStream中
  43. objectOutputStream.writeObject(req);
  44. // 从ByteArrayOutputStream 获取序列化好的字节数组
  45. byte[] byteArray = baos.toByteArray();
  46. return byteArray ;
  47. }
  48. // 反序列化
  49. public static SubscribeReq deserialize(byte[] byteArray) throws Exception{
  50. ObjectInputStream objectOutputStream = new ObjectInputStream(
  51. new ByteArrayInputStream(byteArray));
  52. SubscribeReq req = (SubscribeReq)objectOutputStream.readObject();
  53. return req;
  54. }
  55. }

运行结果:

  1. [-84, -19, 0, 5, 115, 114, 0, 36, 99, 111, 109, 46, 104, 111, 116, 112, 111, 116, 46, 110, 101, 116, 116, 121, 48, 52, 46, 106, 97, 118, 97, 46, 83, 117, 98, 115, 99, 114, 105, 98, 101, 82, 101, 113, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 4, 73, 0, 8, 115, 117, 98, 82, 101, 113, 73, 68, 76, 0, 11, 97, 100, 100, 114, 101, 115, 115, 76, 105, 115, 116, 116, 0, 16, 76, 106, 97, 118, 97, 47, 117, 116, 105, 108, 47, 76, 105, 115, 116, 59, 76, 0, 11, 112, 114, 111, 100, 117, 99, 116, 78, 97, 109, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 76, 0, 8, 117, 115, 101, 114, 78, 97, 109, 101, 113, 0, 126, 0, 2, 120, 112, 0, 0, 0, 1, 115, 114, 0, 19, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 65, 114, 114, 97, 121, 76, 105, 115, 116, 120, -127, -46, 29, -103, -57, 97, -99, 3, 0, 1, 73, 0, 4, 115, 105, 122, 101, 120, 112, 0, 0, 0, 2, 119, 4, 0, 0, 0, 2, 116, 0, 6, -27, -116, -105, -28, -70, -84, 116, 0, 6, -26, -78, -89, -27, -73, -98, 120, 116, 0, 5, 110, 101, 116, 116, 121, 116, 0, 3, 97, 98, 99]

缺点:性能低下。

protobuf序列化

序列化出来的数据很小。实现方式自行百度。

对比一下:

java

  1. [-84, -19, 0, 5, 115, 114, 0, 46, 99, 111, 109, 46, 116, 117, 108, 105, 110, 103, 46, 110, 101, 116, 116, 121, 46, 100, 97, 121, 51,
  2. 46, 106, 97, 118, 97, 46, 115, 101, 114, 105, 97, 108, 46, 83, 117, 98, 115, 99, 114, 105, 98, 101, 82, 101, 113, 0, 0, 0, 0, 0, 0,
  3. 0, 1, 2, 0, 4, 73, 0, 8, 115, 117, 98, 82, 101, 113, 73, 68, 76, 0, 11, 97, 100, 100, 114, 101, 115, 115, 76, 105, 115, 116, 116, 0,
  4. 16, 76, 106, 97, 118, 97, 47, 117, 116, 105, 108, 47, 76, 105, 115, 116, 59, 76, 0, 11, 112, 114, 111, 100, 117, 99, 116, 78, 97,
  5. 109, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 76, 0, 8, 117, 115, 101, 114,
  6. 78, 97, 109, 101, 113, 0, 126, 0, 2, 120, 112, 0, 0, 0, 1, 115, 114, 0, 19, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 65, 114,
  7. 114, 97, 121, 76, 105, 115, 116, 120, -127, -46, 29, -103, -57, 97, -99, 3, 0, 1, 73, 0, 4, 115, 105, 122, 101, 120, 112, 0, 0, 0,
  8. 2, 119, 4, 0, 0, 0, 2, 116, 0, 6, -23, -107, -65, -26, -78, -103, 116, 0, 6, -26, -73, -79, -27, -100, -77, 120, 116, 0, 5, 110,
  9. 101, 116, 116, 121, 116, 0, 3, 97, 98, 99]

Protobuf

  1. [8, 1, 18, 3, 97, 98, 99, 26, 5, 110, 101, 116, 116, 121, 34, 6, -23, -107, -65, -26, -78, -103, 34, 6, -26, -73, -79, -27, -100, -77]

int 内存中: 4个字节 32位

protobuf : 1~5个字节

发表评论

表情:
评论列表 (有 0 条评论,408人围观)

还没有评论,来说两句吧...

相关阅读

    相关 序列序列

    个人学习理解 (只是自己默写序列化和反序列的代码以及几个问题) 1.序列化 和 反序列化 1.1 什么是序列化 和 反序列化 或者 你如何理解序列化和

    相关 序列序列

    序列化: 对象的序列化主要有两种用途:   1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;   2) 在网络上传送对象的字节序列。