Java序列化-Serializable和ProtocolBuffers
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java序列化-Serializable和ProtocolBuffers,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含49247字,纯文字阅读大概需要71分钟。
内容图文
1.什么是Java序列化以及Java序列化的作用
Java平台允许我们在内存中创建可复用的Java对象,一般情况下只有当JVM处于运行时,这些对象才可能存在,所以这些对象的生命周期比 JVM的生命周期更短暂。但现实应用中可能要求JVM在停止运行之后能够保存(持久化)指定的对象,并在之后需要时可重新读取被持久化的对象。Java对象序列化就能够帮助我们实现该要求。但是需要注意,对象序列化static(代表状态)以及transient(代表临时数据)不能够被序列化。
所谓序列化其实就是将程序中的数据通过特定方式保存到本地中。然后把Java对象转换为字节序列的过程称为对象的序列化。核心就是将数据分解成字节流以便存储在文件中或者在网络中传输。就好比我们现在拥有一件体积很大的物品,然后把他尽可能地通过某种方法拆卸变成更小的零件寄出去给被人,别人再通过这种方法把它组装起来变回原本的样子,这一步也就是我们所说的反序列化,Java序列化的过程大概就是这样。
2.什么时候需要Java序列化
1.将内存中的数据保存至数据库或者磁盘文件中。
2.使用套接字进行网络传输数据。
3.对象序列化可以实现分布式对象。使用RMI远程方法调用传输数据。
3.Java序列化的基本使用
使用的比较都的就是对象实现Serializable序列化接口,这个接口的主要作用就是标识该对象可序列化,在传输对象时JRE会进行相应的封装,这里给出一个基本使用的例子。
需要序列化的对象需要先实现Serializable接口
Player.java
package com.serializable;
import java.io.Serializable;
import java.util.List;
/**
* java序列化对象
* @author hzk
* @date 2018/9/20
*/
public class Player implements Serializable{
private static final long serialVersionUID = -1602899989398586421L;
private Integer playerId;
private String name;
private Integer age;
private List<Integer> skills;
public Player(Integer playerId, String name, Integer age,List<Integer> skills) {
this.playerId = playerId;
this.name = name;
this.age = age;
this.skills = skills;
}
public Integer getPlayerId() {
return playerId;
}
public void setPlayerId(Integer playerId) {
this.playerId = playerId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public List<Integer> getSkills() {
return skills;
}
public void setSkills(List<Integer> skills) {
this.skills = skills;
}
}
由于对象已经实现了序列化接口,这里我们对他进行序列化和反序列化操作验证
SerUtils .java
package com.serializable;
import com.google.protobuf.InvalidProtocolBufferException;
import com.proto.PlayerModule;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
/**
* java序列化转换
* @author hzk
* @date 2018/9/20
*/
public class SerUtils {
public static void main(String[] args) throws IOException, ClassNotFoundException {
byte[] bytes = toBytes();
toPlayer(bytes);
}
/**
* 序列化
* @return
* @throws IOException
*/
private static byte[] toBytes() throws IOException {
ArrayList<Integer> integers = new ArrayList<>();
integers.add(10);
Player player = new Player(10, "Peter", 18,integers);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
//写入对象
objectOutputStream.writeObject(player);
//获取字节数据
byte[] bytes = byteArrayOutputStream.toByteArray();
System.out.println(Arrays.toString(bytes));
return bytes;
}
/**
* 反序列化
* @param bs
* @throws InvalidProtocolBufferException
*/
private static void toPlayer(byte[] bs) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(bs));
Player player = (Player) objectInputStream.readObject();
System.out.println("PlayInfo:"+player.getPlayerId()+":"+player.getName()+":"+player.getAge()+":"+player.getSkills());
}
}
运行结果:
[-84, -19, 0, 5, 115, 114, 0, 23, 99, 111, 109, 46, 115, 101, 114, 105, 97, 108, 105, 122, 97, 98, 108, 101, 46, 80, 108, 97, 121, 101, 114, -23, -63, 90, -13, -63, 107, 123, -53, 2, 0, 4, 76, 0, 3, 97, 103, 101, 116, 0, 19, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 73, 110, 116, 101, 103, 101, 114, 59, 76, 0, 4, 110, 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, 112, 108, 97, 121, 101, 114, 73, 100, 113, 0, 126, 0, 1, 76, 0, 6, 115, 107, 105, 108, 108, 115, 116, 0, 16, 76, 106, 97, 118, 97, 47, 117, 116, 105, 108, 47, 76, 105, 115, 116, 59, 120, 112, 115, 114, 0, 17, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 73, 110, 116, 101, 103, 101, 114, 18, -30, -96, -92, -9, -127, -121, 56, 2, 0, 1, 73, 0, 5, 118, 97, 108, 117, 101, 120, 114, 0, 16, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 78, 117, 109, 98, 101, 114, -122, -84, -107, 29, 11, -108, -32, -117, 2, 0, 0, 120, 112, 0, 0, 0, 18, 116, 0, 5, 80, 101, 116, 101, 114, 115, 113, 0, 126, 0, 5, 0, 0, 0, 10, 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, 1, 119, 4, 0, 0, 0, 1, 113, 0, 126, 0, 9, 120]
PlayInfo:10:Peter:18:[10]
4.Protocol Buffers
4.1 什么是Protocol Buffers?
什么是Google Protocol Buffers?网上比较官方的说法是这样的:
Google Protocol Buffers( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。
其实官方的解释已经能够大体解释清楚Protocol buffers是什么,其实它就是一个灵活的、高效的、自动化的用于对结构化数据进行序列化的协议,与XML相比,Protocol buffers序列化后的码流更小、速度更快、操作更简单。我们只需要将要被序列化的数据结构定义一次(使用.proto文件定义),便可以使用特别生成的源代码(使用protobuf提供的生成工具)轻松的使用不同的数据流完成对这些结构数据的读写操作,即使你使用不同的语言(protobuf的跨语言支持特性)。你甚至可以更新你的数据结构的定义(就是更新.proto文件内容)而不会破坏依赖“老”格式编译出来的程序。
4.2 为什么使用Protocol Buffers?
首先我们对比一下普通Java序列化和Protobuf序列化转换字节的区别
Java序列化 | [-84, -19, 0, 5, 115, 114, 0, 15, 99, 111, 109, 46, 106, 97, 118, 97, 46, 80, 108, 97, 121, 101, 114, -73, 43, 28, 39, -119, -86, -125, -3, 2, 0, 4, 73, 0, 3, 97, 103, 101, 74, 0, 8, 112, 108, 97, 121, 101, 114, 73, 100, 76, 0, 4, 110, 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, 6, 115, 107, 105, 108, 108, 115, 116, 0, 16, 76, 106, 97, 118, 97, 47, 117, 116, 105, 108, 47, 76, 105, 115, 116, 59, 120, 112, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 101, 116, 0, 5, 112, 101, 116, 101, 114, 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, 1, 119, 4, 0, 0, 0, 10, 115, 114, 0, 17, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 73, 110, 116, 101, 103, 101, 114, 18, -30, -96, -92, -9, -127, -121, 56, 2, 0, 1, 73, 0, 5, 118, 97, 108, 117, 101, 120, 114, 0, 16, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 78, 117, 109, 98, 101, 114, -122, -84, -107, 29, 11, -108, -32, -117, 2, 0, 0, 120, 112, 0, 0, 3, -23, 120] |
---|---|
ProtoBuf | [8, 101, 16, 20, 26, 5, 112, 101, 116, 101, 114, 32, -23, 7] |
从转换字节的对比上就能很明显发现ProtoBuf的优点之一:数据转换占用空间小
其实ProtoBuf所做的事情在之前更多的是由XML完成,但是ProtoBuf的优点远不止于此,下面几点也是ProtoBuf的会逐渐成为更多开发者序列化数据选择的关键
1.平台无关,语言无关,可扩展;
2.提供了友好的动态库,使用简单;
3.解析速度快,比对应的XML快约20-100倍;
4.序列化数据非常简洁、紧凑,与XML相比,其序列化之后的数据量约为1/3到1/10;
5.自动生成数据访问类方便应用程序的使用;
4.3 Protocol Buffers的基本使用
在使用ProtoBuf之前首先我们需要知道我们要先编写一个.proto文件去指定我们所需要序列化的数据结构。下面在介绍如何使用时会举出这里我们用到的例子,关于ProtoBuf这种数据描述语言这里推荐两篇博客介绍一些规范,可以给大家可以参考一下
Protobuf3语言指南
google protobuf数据类型
player.proto
option java_package = "com.proto";
option java_outer_classname = "PlayerModule";
message PBPlayer{
required int64 playerId = 100;
required int32 age = 10;
required string name = 111;
required int32 skills = 8;
}
message PBResource{
required int64 gold = 8;
required int32 energy = 100;
}
编写好了.proto文件后,我们要生成对应的代码要先从网上将protoc.exe下载下来,这里我一并放在一个目录下方便执行,为了方便生成编写一个.bat脚本
ProtoBuf源码
ProtoBuf程序
build.bat
protoc ./*.proto --java_out=./
pause
使用之前还需要导入对应版本的Jar包
pom.xml
<!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.4.1</version>
</dependency>
执行脚本之后会发现当前目录下自动生成了一个层级目录,里面生成了一个java文件
PlayerModule.java
package com.proto;
public final class PlayerModule {
private PlayerModule() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
}
public interface PBPlayerOrBuilder
extends com.google.protobuf.MessageOrBuilder {
// required int64 playerId = 100;
boolean hasPlayerId();
long getPlayerId();
// required int32 age = 10;
boolean hasAge();
int getAge();
// required string name = 111;
boolean hasName();
String getName();
// required int32 skills = 8;
boolean hasSkills();
int getSkills();
}
public static final class PBPlayer extends
com.google.protobuf.GeneratedMessage
implements PBPlayerOrBuilder {
// Use PBPlayer.newBuilder() to construct.
private PBPlayer(Builder builder) {
super(builder);
}
private PBPlayer(boolean noInit) {}
private static final PBPlayer defaultInstance;
public static PBPlayer getDefaultInstance() {
return defaultInstance;
}
public PBPlayer getDefaultInstanceForType() {
return defaultInstance;
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return com.proto.PlayerModule.internal_static_PBPlayer_descriptor;
}
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return com.proto.PlayerModule.internal_static_PBPlayer_fieldAccessorTable;
}
private int bitField0_;
// required int64 playerId = 100;
public static final int PLAYERID_FIELD_NUMBER = 100;
private long playerId_;
public boolean hasPlayerId() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
public long getPlayerId() {
return playerId_;
}
// required int32 age = 10;
public static final int AGE_FIELD_NUMBER = 10;
private int age_;
public boolean hasAge() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
public int getAge() {
return age_;
}
// required string name = 111;
public static final int NAME_FIELD_NUMBER = 111;
private java.lang.Object name_;
public boolean hasName() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
public String getName() {
java.lang.Object ref = name_;
if (ref instanceof String) {
return (String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
if (com.google.protobuf.Internal.isValidUtf8(bs)) {
name_ = s;
}
return s;
}
}
private com.google.protobuf.ByteString getNameBytes() {
java.lang.Object ref = name_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8((String) ref);
name_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
// required int32 skills = 8;
public static final int SKILLS_FIELD_NUMBER = 8;
private int skills_;
public boolean hasSkills() {
return ((bitField0_ & 0x00000008) == 0x00000008);
}
public int getSkills() {
return skills_;
}
private void initFields() {
playerId_ = 0L;
age_ = 0;
name_ = "";
skills_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized != -1) return isInitialized == 1;
if (!hasPlayerId()) {
memoizedIsInitialized = 0;
return false;
}
if (!hasAge()) {
memoizedIsInitialized = 0;
return false;
}
if (!hasName()) {
memoizedIsInitialized = 0;
return false;
}
if (!hasSkills()) {
memoizedIsInitialized = 0;
return false;
}
memoizedIsInitialized = 1;
return true;
}
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
if (((bitField0_ & 0x00000008) == 0x00000008)) {
output.writeInt32(8, skills_);
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeInt32(10, age_);
}
if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeInt64(100, playerId_);
}
if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeBytes(111, getNameBytes());
}
getUnknownFields().writeTo(output);
}
private int memoizedSerializedSize = -1;
public int getSerializedSize() {
int size = memoizedSerializedSize;
if (size != -1) return size;
size = 0;
if (((bitField0_ & 0x00000008) == 0x00000008)) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(8, skills_);
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(10, age_);
}
if (((bitField0_ & 0x00000001) == 0x00000001)) {
size += com.google.protobuf.CodedOutputStream
.computeInt64Size(100, playerId_);
}
if (((bitField0_ & 0x00000004) == 0x00000004)) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(111, getNameBytes());
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
}
private static final long serialVersionUID = 0L;
@java.lang.Override
protected java.lang.Object writeReplace()
throws java.io.ObjectStreamException {
return super.writeReplace();
}
public static com.proto.PlayerModule.PBPlayer parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static com.proto.PlayerModule.PBPlayer parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static com.proto.PlayerModule.PBPlayer parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static com.proto.PlayerModule.PBPlayer parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static com.proto.PlayerModule.PBPlayer parseFrom(java.io.InputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static com.proto.PlayerModule.PBPlayer parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static com.proto.PlayerModule.PBPlayer parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input)) {
return builder.buildParsed();
} else {
return null;
}
}
public static com.proto.PlayerModule.PBPlayer parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
return builder.buildParsed();
} else {
return null;
}
}
public static com.proto.PlayerModule.PBPlayer parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static com.proto.PlayerModule.PBPlayer parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static Builder newBuilder() { return Builder.create(); }
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder(com.proto.PlayerModule.PBPlayer prototype) {
return newBuilder().mergeFrom(prototype);
}
public Builder toBuilder() { return newBuilder(this); }
@java.lang.Override
protected Builder newBuilderForType(
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder>
implements com.proto.PlayerModule.PBPlayerOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return com.proto.PlayerModule.internal_static_PBPlayer_descriptor;
}
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return com.proto.PlayerModule.internal_static_PBPlayer_fieldAccessorTable;
}
// Construct using com.proto.PlayerModule.PBPlayer.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
}
private Builder(BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
}
}
private static Builder create() {
return new Builder();
}
public Builder clear() {
super.clear();
playerId_ = 0L;
bitField0_ = (bitField0_ & ~0x00000001);
age_ = 0;
bitField0_ = (bitField0_ & ~0x00000002);
name_ = "";
bitField0_ = (bitField0_ & ~0x00000004);
skills_ = 0;
bitField0_ = (bitField0_ & ~0x00000008);
return this;
}
public Builder clone() {
return create().mergeFrom(buildPartial());
}
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return com.proto.PlayerModule.PBPlayer.getDescriptor();
}
public com.proto.PlayerModule.PBPlayer getDefaultInstanceForType() {
return com.proto.PlayerModule.PBPlayer.getDefaultInstance();
}
public com.proto.PlayerModule.PBPlayer build() {
com.proto.PlayerModule.PBPlayer result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
private com.proto.PlayerModule.PBPlayer buildParsed()
throws com.google.protobuf.InvalidProtocolBufferException {
com.proto.PlayerModule.PBPlayer result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(
result).asInvalidProtocolBufferException();
}
return result;
}
public com.proto.PlayerModule.PBPlayer buildPartial() {
com.proto.PlayerModule.PBPlayer result = new com.proto.PlayerModule.PBPlayer(this);
int from_bitField0_ = bitField0_;
int to_bitField0_ = 0;
if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
to_bitField0_ |= 0x00000001;
}
result.playerId_ = playerId_;
if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
to_bitField0_ |= 0x00000002;
}
result.age_ = age_;
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
to_bitField0_ |= 0x00000004;
}
result.name_ = name_;
if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
to_bitField0_ |= 0x00000008;
}
result.skills_ = skills_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
}
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof com.proto.PlayerModule.PBPlayer) {
return mergeFrom((com.proto.PlayerModule.PBPlayer)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(com.proto.PlayerModule.PBPlayer other) {
if (other == com.proto.PlayerModule.PBPlayer.getDefaultInstance()) return this;
if (other.hasPlayerId()) {
setPlayerId(other.getPlayerId());
}
if (other.hasAge()) {
setAge(other.getAge());
}
if (other.hasName()) {
setName(other.getName());
}
if (other.hasSkills()) {
setSkills(other.getSkills());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
public final boolean isInitialized() {
if (!hasPlayerId()) {
return false;
}
if (!hasAge()) {
return false;
}
if (!hasName()) {
return false;
}
if (!hasSkills()) {
return false;
}
return true;
}
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder(
this.getUnknownFields());
while (true) {
int tag = input.readTag();
switch (tag) {
case 0:
this.setUnknownFields(unknownFields.build());
onChanged();
return this;
default: {
if (!parseUnknownField(input, unknownFields,
extensionRegistry, tag)) {
this.setUnknownFields(unknownFields.build());
onChanged();
return this;
}
break;
}
case 64: {
bitField0_ |= 0x00000008;
skills_ = input.readInt32();
break;
}
case 80: {
bitField0_ |= 0x00000002;
age_ = input.readInt32();
break;
}
case 800: {
bitField0_ |= 0x00000001;
playerId_ = input.readInt64();
break;
}
case 890: {
bitField0_ |= 0x00000004;
name_ = input.readBytes();
break;
}
}
}
}
private int bitField0_;
// required int64 playerId = 100;
private long playerId_ ;
public boolean hasPlayerId() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
public long getPlayerId() {
return playerId_;
}
public Builder setPlayerId(long value) {
bitField0_ |= 0x00000001;
playerId_ = value;
onChanged();
return this;
}
public Builder clearPlayerId() {
bitField0_ = (bitField0_ & ~0x00000001);
playerId_ = 0L;
onChanged();
return this;
}
// required int32 age = 10;
private int age_ ;
public boolean hasAge() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
public int getAge() {
return age_;
}
public Builder setAge(int value) {
bitField0_ |= 0x00000002;
age_ = value;
onChanged();
return this;
}
public Builder clearAge() {
bitField0_ = (bitField0_ & ~0x00000002);
age_ = 0;
onChanged();
return this;
}
// required string name = 111;
private java.lang.Object name_ = "";
public boolean hasName() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
public String getName() {
java.lang.Object ref = name_;
if (!(ref instanceof String)) {
String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
name_ = s;
return s;
} else {
return (String) ref;
}
}
public Builder setName(String value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000004;
name_ = value;
onChanged();
return this;
}
public Builder clearName() {
bitField0_ = (bitField0_ & ~0x00000004);
name_ = getDefaultInstance().getName();
onChanged();
return this;
}
void setName(com.google.protobuf.ByteString value) {
bitField0_ |= 0x00000004;
name_ = value;
onChanged();
}
// required int32 skills = 8;
private int skills_ ;
public boolean hasSkills() {
return ((bitField0_ & 0x00000008) == 0x00000008);
}
public int getSkills() {
return skills_;
}
public Builder setSkills(int value) {
bitField0_ |= 0x00000008;
skills_ = value;
onChanged();
return this;
}
public Builder clearSkills() {
bitField0_ = (bitField0_ & ~0x00000008);
skills_ = 0;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:PBPlayer)
}
static {
defaultInstance = new PBPlayer(true);
defaultInstance.initFields();
}
// @@protoc_insertion_point(class_scope:PBPlayer)
}
public interface PBResourceOrBuilder
extends com.google.protobuf.MessageOrBuilder {
// required int64 gold = 8;
boolean hasGold();
long getGold();
// required int32 energy = 100;
boolean hasEnergy();
int getEnergy();
}
public static final class PBResource extends
com.google.protobuf.GeneratedMessage
implements PBResourceOrBuilder {
// Use PBResource.newBuilder() to construct.
private PBResource(Builder builder) {
super(builder);
}
private PBResource(boolean noInit) {}
private static final PBResource defaultInstance;
public static PBResource getDefaultInstance() {
return defaultInstance;
}
public PBResource getDefaultInstanceForType() {
return defaultInstance;
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return com.proto.PlayerModule.internal_static_PBResource_descriptor;
}
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return com.proto.PlayerModule.internal_static_PBResource_fieldAccessorTable;
}
private int bitField0_;
// required int64 gold = 8;
public static final int GOLD_FIELD_NUMBER = 8;
private long gold_;
public boolean hasGold() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
public long getGold() {
return gold_;
}
// required int32 energy = 100;
public static final int ENERGY_FIELD_NUMBER = 100;
private int energy_;
public boolean hasEnergy() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
public int getEnergy() {
return energy_;
}
private void initFields() {
gold_ = 0L;
energy_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized != -1) return isInitialized == 1;
if (!hasGold()) {
memoizedIsInitialized = 0;
return false;
}
if (!hasEnergy()) {
memoizedIsInitialized = 0;
return false;
}
memoizedIsInitialized = 1;
return true;
}
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeInt64(8, gold_);
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeInt32(100, energy_);
}
getUnknownFields().writeTo(output);
}
private int memoizedSerializedSize = -1;
public int getSerializedSize() {
int size = memoizedSerializedSize;
if (size != -1) return size;
size = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) {
size += com.google.protobuf.CodedOutputStream
.computeInt64Size(8, gold_);
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(100, energy_);
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
}
private static final long serialVersionUID = 0L;
@java.lang.Override
protected java.lang.Object writeReplace()
throws java.io.ObjectStreamException {
return super.writeReplace();
}
public static com.proto.PlayerModule.PBResource parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static com.proto.PlayerModule.PBResource parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static com.proto.PlayerModule.PBResource parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static com.proto.PlayerModule.PBResource parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static com.proto.PlayerModule.PBResource parseFrom(java.io.InputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static com.proto.PlayerModule.PBResource parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static com.proto.PlayerModule.PBResource parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input)) {
return builder.buildParsed();
} else {
return null;
}
}
public static com.proto.PlayerModule.PBResource parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
return builder.buildParsed();
} else {
return null;
}
}
public static com.proto.PlayerModule.PBResource parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static com.proto.PlayerModule.PBResource parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static Builder newBuilder() { return Builder.create(); }
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder(com.proto.PlayerModule.PBResource prototype) {
return newBuilder().mergeFrom(prototype);
}
public Builder toBuilder() { return newBuilder(this); }
@java.lang.Override
protected Builder newBuilderForType(
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder>
implements com.proto.PlayerModule.PBResourceOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return com.proto.PlayerModule.internal_static_PBResource_descriptor;
}
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return com.proto.PlayerModule.internal_static_PBResource_fieldAccessorTable;
}
// Construct using com.proto.PlayerModule.PBResource.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
}
private Builder(BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
}
}
private static Builder create() {
return new Builder();
}
public Builder clear() {
super.clear();
gold_ = 0L;
bitField0_ = (bitField0_ & ~0x00000001);
energy_ = 0;
bitField0_ = (bitField0_ & ~0x00000002);
return this;
}
public Builder clone() {
return create().mergeFrom(buildPartial());
}
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return com.proto.PlayerModule.PBResource.getDescriptor();
}
public com.proto.PlayerModule.PBResource getDefaultInstanceForType() {
return com.proto.PlayerModule.PBResource.getDefaultInstance();
}
public com.proto.PlayerModule.PBResource build() {
com.proto.PlayerModule.PBResource result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
private com.proto.PlayerModule.PBResource buildParsed()
throws com.google.protobuf.InvalidProtocolBufferException {
com.proto.PlayerModule.PBResource result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(
result).asInvalidProtocolBufferException();
}
return result;
}
public com.proto.PlayerModule.PBResource buildPartial() {
com.proto.PlayerModule.PBResource result = new com.proto.PlayerModule.PBResource(this);
int from_bitField0_ = bitField0_;
int to_bitField0_ = 0;
if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
to_bitField0_ |= 0x00000001;
}
result.gold_ = gold_;
if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
to_bitField0_ |= 0x00000002;
}
result.energy_ = energy_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
}
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof com.proto.PlayerModule.PBResource) {
return mergeFrom((com.proto.PlayerModule.PBResource)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(com.proto.PlayerModule.PBResource other) {
if (other == com.proto.PlayerModule.PBResource.getDefaultInstance()) return this;
if (other.hasGold()) {
setGold(other.getGold());
}
if (other.hasEnergy()) {
setEnergy(other.getEnergy());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
public final boolean isInitialized() {
if (!hasGold()) {
return false;
}
if (!hasEnergy()) {
return false;
}
return true;
}
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder(
this.getUnknownFields());
while (true) {
int tag = input.readTag();
switch (tag) {
case 0:
this.setUnknownFields(unknownFields.build());
onChanged();
return this;
default: {
if (!parseUnknownField(input, unknownFields,
extensionRegistry, tag)) {
this.setUnknownFields(unknownFields.build());
onChanged();
return this;
}
break;
}
case 64: {
bitField0_ |= 0x00000001;
gold_ = input.readInt64();
break;
}
case 800: {
bitField0_ |= 0x00000002;
energy_ = input.readInt32();
break;
}
}
}
}
private int bitField0_;
// required int64 gold = 8;
private long gold_ ;
public boolean hasGold() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
public long getGold() {
return gold_;
}
public Builder setGold(long value) {
bitField0_ |= 0x00000001;
gold_ = value;
onChanged();
return this;
}
public Builder clearGold() {
bitField0_ = (bitField0_ & ~0x00000001);
gold_ = 0L;
onChanged();
return this;
}
// required int32 energy = 100;
private int energy_ ;
public boolean hasEnergy() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
public int getEnergy() {
return energy_;
}
public Builder setEnergy(int value) {
bitField0_ |= 0x00000002;
energy_ = value;
onChanged();
return this;
}
public Builder clearEnergy() {
bitField0_ = (bitField0_ & ~0x00000002);
energy_ = 0;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:PBResource)
}
static {
defaultInstance = new PBResource(true);
defaultInstance.initFields();
}
// @@protoc_insertion_point(class_scope:PBResource)
}
private static com.google.protobuf.Descriptors.Descriptor
internal_static_PBPlayer_descriptor;
private static
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_PBPlayer_fieldAccessorTable;
private static com.google.protobuf.Descriptors.Descriptor
internal_static_PBResource_descriptor;
private static
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_PBResource_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\014player.proto\"G\n\010PBPlayer\022\020\n\010playerId\030d" +
" \002(\003\022\013\n\003age\030\n \002(\005\022\014\n\004name\030o \002(\t\022\016\n\006skill" +
"s\030\010 \002(\005\"*\n\nPBResource\022\014\n\004gold\030\010 \002(\003\022\016\n\006e" +
"nergy\030d \002(\005B\031\n\tcom.protoB\014PlayerModule"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
public com.google.protobuf.ExtensionRegistry assignDescriptors(
com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root;
internal_static_PBPlayer_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_PBPlayer_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_PBPlayer_descriptor,
new java.lang.String[] { "PlayerId", "Age", "Name", "Skills", },
com.proto.PlayerModule.PBPlayer.class,
com.proto.PlayerModule.PBPlayer.Builder.class);
internal_static_PBResource_descriptor =
getDescriptor().getMessageTypes().get(1);
internal_static_PBResource_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_PBResource_descriptor,
new java.lang.String[] { "Gold", "Energy", },
com.proto.PlayerModule.PBResource.class,
com.proto.PlayerModule.PBResource.Builder.class);
return null;
}
};
com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
}, assigner);
}
// @@protoc_insertion_point(outer_class_scope)
}
这里一大串代码都是ProtoBuf根据我们自己编写的.proto文件自动生成的,这里我们来简单地使用达成和Java序列化一样的效果
PBUtils.java
package com.proto;
import com.google.protobuf.InvalidProtocolBufferException;
import java.util.Arrays;
/**
* protocol buffers 转换
* @author hzk
* @date 2018/9/20
*/
public class PBUtils {
public static void main(String[] args) throws InvalidProtocolBufferException {
byte[] bytes = toBytes();
toPlayer(bytes);
}
/**
* 序列化
* @return
*/
private static byte[] toBytes(){
//获取PBPlayer构造器
PlayerModule.PBPlayer.Builder builder = PlayerModule.PBPlayer.newBuilder();
//设置数据
builder.setName("hhh").setAge(10).setSkills(10).setPlayerId(1);
//构造对象
PlayerModule.PBPlayer player = builder.build();
//序列化成字节数组
//This is supposed to be overridden by subclasses. 需要maven引用和生成java文件的版本相同
byte[] bytes = player.toByteArray();
System.out.println(Arrays.toString(bytes));
return bytes;
}
/**
* 反序列化
* @param bs
* @throws InvalidProtocolBufferException
*/
private static void toPlayer(byte[] bs) throws InvalidProtocolBufferException {
PlayerModule.PBPlayer player = PlayerModule.PBPlayer.parseFrom(bs);
System.out.println("PlayInfo:"+player.getPlayerId()+":"+player.getName()+":"+player.getAge()+":"+player.getSkills());
}
}
运行结果:
[64, 10, 80, 10, -96, 6, 1, -6, 6, 3, 104, 104, 104]
PlayInfo:1:hhh:10:10
简单几步就能利用protobuf序列化我们需要的数据对象,并且可以发现序列化和反序列化的效率都十分高
5.自定义序列化协议
根据不同的业务需求和不同的应用场景,我们可能需要采取不同的序列化方式,开发人员也会根据具体需要自定义所需序列化规则,这里介绍几种大家可能会接触到的自定义协议规则
第一种用的是大端字节序列,先写高位再写低位
大端 小端和网络字节序说明
Test1.java
package com.customSerializable.test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
/**
* @author hzk
* @date 2018/9/25
*/
public class Test1 {
public static void main(String[] args) throws IOException {
int id = 111; // 0110 1111
int age = 23; //0001 0111
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] idBytes = int2byte(id);
byte[] ageBytes = int2byte(age);
System.out.println("Bytes id:"+ Arrays.toString(idBytes));
System.out.println("Bytes age:"+ Arrays.toString(ageBytes));
byteArrayOutputStream.write(idBytes);
byteArrayOutputStream.write(ageBytes);
byte[] outBytes = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outBytes);
byte[] idBytesIn = new byte[4];
byteArrayInputStream.read(idBytesIn);
System.out.println("Read Bytes id:"+Arrays.toString(idBytesIn));
System.out.println("Read Bytes Trans id:"+byte2int(idBytesIn));
byte[] ageBytesIn = new byte[4];
byteArrayInputStream.read(ageBytesIn);
System.out.println("Read Bytes age:"+Arrays.toString(ageBytesIn));
System.out.println("Read Bytes Trans age:"+byte2int(ageBytesIn));
}
/**
* 大端字节序列(先写高位,再写低位)
* @param i
* @return
*/
private static byte[] int2byte(int i){
byte[] bytes = new byte[4];
bytes[0] = (byte)(i >> 3*8);
bytes[1] = (byte)(i >> 2*8);
bytes[2] = (byte)(i >> 1*8);
bytes[3] = (byte)(i >> 0*8);
return bytes;
}
/**
* 大端字节反序列
* @param bytes
* @return
*/
private static int byte2int(byte[] bytes){
return (bytes[0] << 3*8)|(bytes[1] << 2*8)|(bytes[2] << 1*8)|(bytes[3] << 0*8);
}
}
运行结果:
Bytes id:[0, 0, 0, 111]
Bytes age:[0, 0, 0, 23]
Read Bytes id:[0, 0, 0, 111]
Read Bytes Trans id:111
Read Bytes age:[0, 0, 0, 23]
Read Bytes Trans age:23
第二种用到了NIO中提供的ByteBuffer,相比上面的方法更加方便就能分解成字节数据,但是缺点是需要指定要转换数据的字节大小
Test2.java
package com.customSerializable.test;
import java.nio.ByteBuffer;
import java.util.Arrays;
/**
* ByteBuffer 需要指定大小
* @author hzk
* @date 2018/9/26
*/
public class Test2 {
public static void main(String[] args){
int id = 111;
int age = 23;
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putInt(id);
buffer.putInt(age);
byte[] array = buffer.array();
System.out.println(Arrays.toString(array));
ByteBuffer wrap = ByteBuffer.wrap(array);
System.out.println(wrap.getInt());
System.out.println(wrap.getInt());
}
}
运行结果:
[0, 0, 0, 111, 0, 0, 0, 23]
111
23
第三种借助了Netty提供的ChannelBuffers,可以利用该对象动态生成缓冲字节数据的ChannelBuffer
pom.xml
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
<version>3.10.5.Final</version>
</dependency>
Test3.java
package com.customSerializable.test;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import java.util.Arrays;
/**
* ChannelBuffers Netty工具
* @author hzk
* @date 2018/9/26
*/
public class Test3 {
public static void main(String[] args){
ChannelBuffer channelBuffer = ChannelBuffers.dynamicBuffer();
channelBuffer.writeInt(111);
channelBuffer.writeDouble(23.5);
byte[] bytes = new byte[channelBuffer.writerIndex()];
channelBuffer.readBytes(bytes);
System.out.println(Arrays.toString(bytes));
ChannelBuffer channelBuffer1 = ChannelBuffers.wrappedBuffer(bytes);
System.out.println(channelBuffer1.readInt());
System.out.println(channelBuffer1.readDouble());
}
}
运行结果:
[0, 0, 0, 111, 64, 55, -128, 0, 0, 0, 0, 0]
111
23.5
第四种利用Netty提供的ChannelBuffers根据自定义的规则(例如序列化String字符串类型数据时,首先写入一个short类型数据表示该字符串转换为字节数组的长度,再写入具体的字节数据,集合亦是如此)封装一个自定义序列化抽象类以供需要序列化的数据继承使用
BufferFactory.java
package com.customSerializable.core;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import java.nio.ByteOrder;
/**
* ChannelBuffers工具类
* @author hzk
* @date 2018/9/26
*/
public class BufferFactory{
public static ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN;
/**
* 获取一个ChannelBuffer
* @return
*/
public static ChannelBuffer getBuffer(){
ChannelBuffer channelBuffer = ChannelBuffers.dynamicBuffer();
return channelBuffer;
}
/**
* 获取一个ChannelBuffer 并写入数据
* @param bytes
* @return
*/
public static ChannelBuffer getBuffer(byte[] bytes){
ChannelBuffer channelBuffer = ChannelBuffers.copiedBuffer(bytes);
return channelBuffer;
}
}
AbstractSerializable.java
package com.customSerializable.core;
import org.jboss.netty.buffer.ChannelBuffer;
import java.nio.charset.Charset;
import java.util.*;
/**
* 自定义序列化
* @author hzk
* @date 2018/9/26
*/
public abstract class AbstractSerializable {
public static final Charset CHARSET = Charset.forName("UTF-8");
protected ChannelBuffer writeBuffer;
protected ChannelBuffer readBuffer;
/**
* 反序列化具体实现
*/
protected abstract void read();
/**
* 序列化具体实现
*/
protected abstract void write();
/**
* 从bytes数组读取数据
* @param bytes
* @return
*/
public AbstractSerializable readFromBytes(byte[] bytes){
readBuffer = BufferFactory.getBuffer(bytes);
read();
readBuffer.clear();
return this;
}
/**
* 从channelBuffer读取数据
* @param channelBuffer
*/
public void readFromBuffer(ChannelBuffer channelBuffer){
this.readBuffer = channelBuffer;
read();
}
/**
* 写入到本地channelBuffer
* @return
*/
public ChannelBuffer writeToLocalBuffer(){
this.writeBuffer = BufferFactory.getBuffer();
write();
return writeBuffer;
}
/**
* 写入到目标channelBuffer
* @param channelBuffer
* @return
*/
public ChannelBuffer writeToTargetBuffer(ChannelBuffer channelBuffer){
this.writeBuffer = channelBuffer;
write();
return writeBuffer;
}
public AbstractSerializable writeByte(Byte value){
writeBuffer.writeByte(value);
return this;
}
public AbstractSerializable writeInt(int value){
writeBuffer.writeInt(value);
return this;
}
public AbstractSerializable writeShort(short value){
writeBuffer.writeShort(value);
return this;
}
public AbstractSerializable writeLong(long value){
writeBuffer.writeLong(value);
return this;
}
public AbstractSerializable writeFloat(float value){
writeBuffer.writeFloat(value);
return this;
}
public AbstractSerializable writeDouble(double value){
writeBuffer.writeDouble(value);
return this;
}
public AbstractSerializable writeString(String value){
if(null == value || value.isEmpty()){
writeShort((short)0);
return this;
}
byte[] bytes = value.getBytes(CHARSET);
short size = (short) bytes.length;
writeBuffer.writeShort(size);
writeBuffer.writeBytes(bytes);
return this;
}
public AbstractSerializable writeObject(Object object){
if(null == object){
writeByte((byte)0);
}else{
if(object instanceof Integer){
writeInt((int)object);
}else if(object instanceof Short){
writeShort((short)object);
}else if(object instanceof Byte){
writeByte((byte)object);
}else if(object instanceof Long){
writeLong((long)object);
}else if(object instanceof Float){
writeFloat((float)object);
}else if(object instanceof Double){
writeDouble((double)object);
}else if(object instanceof String){
writeString((String) object);
}else if(object instanceof AbstractSerializable){
writeByte((byte)1);
AbstractSerializable serializable = (AbstractSerializable) object;
serializable.writeToTargetBuffer(writeBuffer);
}else{
throw new RuntimeException("不可序列化类型:[%s]"+object.getClass());
}
}
return this;
}
public <T> AbstractSerializable writeList(List<T> list){
if(isEmpty(list)){
writeBuffer.writeShort((short)0);
return this;
}
writeBuffer.writeShort((short)list.size());
for(T t:list){
writeObject(t);
}
return this;
}
public <K,V> AbstractSerializable writeMap(Map<K,V> map){
if(isEmpty(map)){
writeBuffer.writeShort((short)0);
return this;
}
writeBuffer.writeShort((short)map.size());
for (Map.Entry<K,V> entry:map.entrySet()) {
writeObject(entry.getKey());
writeObject(entry.getValue());
}
return this;
}
/**
* 返回byte数组
* @return
*/
public byte[] getBytes(){
writeToLocalBuffer();
byte[] bytes = null;
if(writeBuffer.writerIndex() == 0){
bytes = new byte[0];
}else{
bytes = new byte[writeBuffer.writerIndex()];
writeBuffer.readBytes(bytes);
}
writeBuffer.clear();
return bytes;
}
public byte readByte(){
return readBuffer.readByte();
}
public short readShort(){
return readBuffer.readShort();
}
public int readInt(){
return readBuffer.readInt();
}
public long readLong(){
return readBuffer.readLong();
}
public float readFloat(){
return readBuffer.readFloat();
}
public double readDouble(){
return readBuffer.readDouble();
}
public String readString(){
short size = readBuffer.readShort();
if(size <= 0){
return "";
}
byte[] bytes = new byte[size];
readBuffer.readBytes(bytes);
return new String(bytes,CHARSET);
}
public <K> K readObject(Class<K> clz){
Object k = null;
if(clz == int.class || clz == Integer.class){
k = readInt();
}else if(clz == byte.class || clz == Byte.class){
k = readByte();
}else if(clz == short.class || clz == Short.class){
k = readShort();
}else if(clz == long.class || clz == Long.class){
k = readLong();
}else if(clz == float.class || clz == Float.class){
k = readFloat();
}else if(clz == double.class || clz == Double.class){
k = readDouble();
}else if(clz == String.class){
k = readString();
}else if(AbstractSerializable.class.isAssignableFrom(clz)){
try {
byte hasObject = readBuffer.readByte();
if(hasObject == 1){
AbstractSerializable temp = (AbstractSerializable) clz.newInstance();
temp.readFromBuffer(readBuffer);
k = temp;
}else{
k = null;
}
}catch (Exception e){
e.printStackTrace();
}
}else{
throw new RuntimeException(String.format("不支持类型:[%s]",clz));
}
return (K)k;
}
public <T> List<T> readList(Class<T> clz){
ArrayList<T> list = new ArrayList<>();
short size = readBuffer.readShort();
for(int i=0;i<size;i++){
list.add(readObject(clz));
}
return list;
}
public <K,V> Map<K,V> readMap(Class<K> keyClz,Class<V> valueClz){
HashMap<K, V> map = new HashMap<>();
short size = readBuffer.readShort();
for (int i =0;i<size;i++){
K key = readObject(keyClz);
V value = readObject(valueClz);
map.put(key,value);
}
return map;
}
private <T> boolean isEmpty(Collection<T> c) {
return c == null || c.isEmpty();
}
public <K,V> boolean isEmpty(Map<K,V> c) {
return c == null || c.isEmpty();
}
}
Resource.java
package com.customSerializable.entity;
import com.customSerializable.core.AbstractSerializable;
/**
* @author hzk
* @date 2018/9/27
*/
public class Resource extends AbstractSerializable {
/**
* 体力
*/
private Integer energy;
/**
* 金币
*/
private Double gold;
public Integer getEnergy() {
return energy;
}
public void setEnergy(Integer energy) {
this.energy = energy;
}
public Double getGold() {
return gold;
}
public void setGold(Double gold) {
this.gold = gold;
}
@Override
protected void read() {
energy = readInt();
gold = readDouble();
}
@Override
protected void write() {
writeInt(energy);
writeDouble(gold);
}
@Override
public String toString() {
return "Resource{" +
"energy=" + energy +
", gold=" + gold +
'}';
}
}
Player.java
package com.customSerializable.entity;
import com.customSerializable.core.AbstractSerializable;
import java.util.ArrayList;
import java.util.List;
/**
* @author hzk
* @date 2018/9/27
*/
public class Player extends AbstractSerializable {
private Long playerId;
private Integer age;
private List<Integer> skills = new ArrayList<>();
private Resource resource = new Resource();
public Long getPlayerId() {
return playerId;
}
public void setPlayerId(Long playerId) {
this.playerId = playerId;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public List<Integer> getSkills() {
return skills;
}
public void setSkills(List<Integer> skills) {
this.skills = skills;
}
public Resource getResource() {
return resource;
}
public void setResource(Resource resource) {
this.resource = resource;
}
@Override
protected void read() {
playerId = readLong();
age = readInt();
skills = readList(Integer.class);
resource = readObject(Resource.class);
}
@Override
protected void write() {
writeLong(playerId);
writeInt(age);
writeList(skills);
writeObject(resource);
}
@Override
public String toString() {
return "Player{" +
"playerId=" + playerId +
", age=" + age +
", skills=" + skills +
", resource=" + resource +
'}';
}
}
Test4.java
package com.customSerializable.test;
import com.customSerializable.entity.Player;
import java.util.Arrays;
/**
* 自定义序列化
* @author hzk
* @date 2018/9/27
*/
public class Test4 {
public static void main(String[] args){
Player player = new Player();
player.setPlayerId(1111L);
player.setAge(23);
player.getSkills().add(77);
player.getSkills().add(88);
player.getResource().setEnergy(100);
player.getResource().setGold(15000.00D);
byte[] bytes = player.getBytes();
System.out.println(Arrays.toString(bytes));
Player player2 = new Player();
player2.readFromBytes(bytes);
System.out.println(player2.toString());
}
}
运行结果:
[0, 0, 0, 0, 0, 0, 4, 87, 0, 0, 0, 23, 0, 2, 0, 0, 0, 77, 0, 0, 0, 88, 1, 0, 0, 0, 100, 64, -51, 76, 0, 0, 0, 0, 0]
Player{playerId=1111, age=23, skills=[77, 88], resource=Resource{energy=100, gold=15000.0}}
最后这种方式是基于前面几种方式技术和思维的一些结合,不管怎样去实现序列化都有我们需要注意的一件事就是写入和读取的顺序需要一致,否则数据无法匹配正确,关于序列化还有很多更深层次的知识,如果大家有需要可以自己去深入了解。
内容总结
以上是互联网集市为您收集整理的Java序列化-Serializable和ProtocolBuffers全部内容,希望文章能够帮你解决Java序列化-Serializable和ProtocolBuffers所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。