netty04-序列化反序列化
序列化协议基础
基础类型int在内存中的原始序列化
基于nio的序列化
基于netty的序列化
int类型序列化
int类型序列化方式有两种
大端序列:先写高位,在写低位
小端序列:先写低位,在写高位
左边是高位 右边是低位
00000000 00000000 00000000 00001011 = 11
/**
* 将int数值转换为占四个字节的byte数组, 低位在前,高位在后
*/
public static byte[] intToBytes(int value)
{
byte[] byteArray = new byte[4];
// 最高位放在最后一个字节 ,也就是向右移动3个字节 = 24位
byteArray[3] = (byte) ((value & 0xFF000000)>>3*8);// 最高位,放在字节数组最后
byteArray[2] = (byte) ((value & 0x00FF0000)>>2*8);// 左边第二个字节
byteArray[1] = (byte) ((value & 0x0000FF00)>>1*8);
byteArray[0] = (byte) ((value & 0x000000FF)); // 最低位
//[11,0,0,0]
return byteArray;
}
value & 0xFF000000解释:
00000000 00000000 00000000 00001011
& 11111111 00000000 00000000 00000000
= 00000000 00000000 00000000 00000000 = 0
int类型反序列化
/**
* byte数组转int; 低位在前,高位在后
*/
public static int bytesToInt(byte[] byteArray) {
return (byteArray[0]&0xFF)|
((byteArray[1]<<1*8) & 0xFF00)|
((byteArray[2]<<2*8) & 0xFF0000)|
((byteArray[3]<<3*8) & 0xFF000000);
}
写个测试方法,代码如下:
public static void main(String[] args) throws Exception {
int a = 11;
int b = 22;
int c = 88;
ByteArrayOutputStream os = new ByteArrayOutputStream();
//os.write(a);// 为什么不用这个?
os.write(intToBytes(a));
os.write(intToBytes(b));
os.write(intToBytes(c));
byte[] byteArray = os.toByteArray();
System.out.println(Arrays.toString(byteArray));
ByteArrayInputStream is = new ByteArrayInputStream(byteArray);
byte[] aBytes = new byte[4];
byte[] bBytes = new byte[4];
byte[] cBytes = new byte[4];
is.read(aBytes);
is.read(bBytes);
is.read(cBytes);
System.out.println("a: " + bytesToInt(aBytes));
System.out.println("b: " + bytesToInt(bBytes));
System.out.println("c: " + bytesToInt(cBytes));
}
运行结果:
nio序列化反序列化
public static void main(String[] args) {
int a = 11;
int b = 22;
// 序列化
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putInt(a);
buffer.putInt(b);
// buffer.putInt(2);
byte[] array = buffer.array();
System.out.println(Arrays.toString(buffer.array()));
// 反序列化
ByteBuffer bb = ByteBuffer.wrap(array);
System.out.println("a: " + bb.getInt());
System.out.println("b: " + bb.getInt());
}
对比传统序列化可以看出简便很多,但是也有缺点就是ByteBuffer不是动态扩容的,默认是多少是不能增加的。即解决复杂的运算但是不支持扩容。有没有两者兼得的呢?netty。。。
netty序列化反序列化
public static void main(String[] args) {
ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
buffer.writeInt(11);
buffer.writeInt(22);
buffer.writeLong(23);
buffer.writeLong(23);
// byte数组的大小由buffer中写指针的位置决定
// 往ChannelBuffer中写数据的时候,这个写指针就会移动写的数据的长度
byte[] bytes = new byte[buffer.writerIndex()];
buffer.readBytes(bytes); // 序列化
System.out.println(Arrays.toString(bytes));
// 反序列化
ChannelBuffer wrappedBuffer = ChannelBuffers.wrappedBuffer(bytes);
System.out.println(wrappedBuffer.readInt());
System.out.println(wrappedBuffer.readInt());
}
对象序列化
Java原始对象序列化
ObjectInputStream,ObjectOutStream
package com.hotpot.netty04.java;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 描述:java原始序列化
* ObjectOutputStream 序列化
* ObjectInputStream 反序列化
* @author: myx
* @date: 2018/2/7 0007
* Copyright © 2018-ganinfo. All rights reserved.
*/
public class JavaSeri {
public static void main(String[] args) throws Exception{
// 序列化
byte[] result = serialize();
System.out.println(Arrays.toString(result));
// 反序列化
SubscribeReq req = deserialize(result);
System.out.println(req.getSubReqID());
System.out.println(req.getUserName());
System.out.println(req.getProductName());
System.out.println(req.getAddressList().get(0));
System.out.println(req.getAddressList().get(1));
}
// 序列化
public static byte[] serialize() throws Exception{
SubscribeReq req = new SubscribeReq();
req.setSubReqID(1);
req.setUserName("abc");
req.setProductName("netty");
List<String> addressList = new ArrayList<String>();
addressList.add("北京");
addressList.add("沧州");
req.setAddressList(addressList);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos);
// 把SubscribeReq对象写入ByteArrayOutputStream中
objectOutputStream.writeObject(req);
// 从ByteArrayOutputStream 获取序列化好的字节数组
byte[] byteArray = baos.toByteArray();
return byteArray ;
}
// 反序列化
public static SubscribeReq deserialize(byte[] byteArray) throws Exception{
ObjectInputStream objectOutputStream = new ObjectInputStream(
new ByteArrayInputStream(byteArray));
SubscribeReq req = (SubscribeReq)objectOutputStream.readObject();
return req;
}
}
运行结果:
[-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
[-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,
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,
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, -23, -107, -65, -26, -78, -103, 116, 0, 6, -26, -73, -79, -27, -100, -77, 120, 116, 0, 5, 110,
101, 116, 116, 121, 116, 0, 3, 97, 98, 99]
Protobuf
[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个字节
还没有评论,来说两句吧...