java编解码技术
来源:互联网 发布:网络教育试点高校 编辑:程序博客网 时间:2024/05/15 02:25
一.编解码技术
基于Java提供的对象输入/输出ObjectInputStream和ObjectOutputStream,可以直接把Java对象作为可存储的字节数组写入文件,也可以传输到网络上,对于程序员来说,基于JDK默认的序列化机制可以避免操作底层字节数组,从而提升开发效率。
当进行进程跨进程的调用时,需要把被传输的Java对象编码为字节数组或者ByteBuffer对象,而当远程服务收到字节数组或者ByteBuffer时,需要将其解码为Java对象。这被称为Java对象编解码技术。
二.Java序列化
Java序列化从JDK1.1版本就已经提供,只需要实现java.io.Serializable即可,但是进行远程服务调用(RPC)时,却很少使用Java序列化进行消息的编解编码和传输,主要原因是:
1). 无法跨语言,Java序列化技术是Java语言内部的私有协议,其他语言并不支持,对于Java序列化后的字节数组,别的语言无法进行反序列化,这就严重阻碍它的应用。
2). 序列化后流太大
3).序列化性能太低
ps一句其他的:
1). Serializable序列化生成serialVersionUID的两种方式,一个是默认的1L,另一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段。
2). 显示设置serialVersionUID 与不设置serialVersionUID的区别,显示设置serialVersionUID确保了不同版本之间的兼容性,不仅能够向前兼容,还能够向后兼容,即在版 升级时反序列化仍保持对象的唯一 性 ; 不设置serialVersionUID时,默认生成一个serialVersionUID,本地实体类有修改后又生成 一个serialVersionUID,在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致 的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException);
3). 声明为transient类型的成员数据不能被序列化。transient代表对象的临时数据;
三.Java序列和ByteBuffer的二进制序列对比
1). 待序列化类
package com.phei.netty;import java.io.Serializable;public class UserInfo implements Serializable {private static final long serialVersionUID = -5867548109897989552L; private String userName; private int userID; public UserInfo(String userName,int userID){ this.userName = userName; this.userID = userID; }public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public int getUserID() {return userID;}public void setUserID(int userID) {this.userID = userID;} }
2).测试类
<pre name="code" class="java">package com.phei.netty;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.nio.ByteBuffer;public class UserInfoTest {public static void main(String args[]) throws IOException{UserInfo user = new UserInfo("Hello World", 666666);System.out.println("/*-------------------序列号字节流长度对比--------------------------*/");ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(user);oos.flush();oos.close();byte [] b = bos.toByteArray();System.out.println("Java jdk自带的序列化字节流的大小"+b.length);bos.close();ByteBuffer buffer = ByteBuffer.allocate(1024);buffer.put(user.getUserName().getBytes());buffer.putInt(user.getUserID());buffer.flip();byte [] result = new byte[buffer.remaining()];buffer.get(result);System.out.println("ByteBuffer的二进制压缩后字节流的大小"+result.length);System.out.println();System.out.println("/*-------------------序列号性能对比--------------------------*/");long startTimeMillis = System.currentTimeMillis();for(int i=0;i<1000;i++){ByteArrayOutputStream bo = new ByteArrayOutputStream();ObjectOutputStream oo = new ObjectOutputStream(bos);oos.writeObject(user);oos.flush();oos.close();byte [] bb = bos.toByteArray();bos.close();}System.out.println("Java 自带序列化花费时间:"+(System.currentTimeMillis()-startTimeMillis));long startTimeMil = System.currentTimeMillis();for(int i=0;i<1000;i++){ByteBuffer buf = ByteBuffer.allocate(1024);buf.put(user.getUserName().getBytes());buf.putInt(user.getUserID());buf.flip();byte [] res = new byte[buf.remaining()];buf.get(res);}System.out.println("ByteBuffer的序列化花费时间:"+(System.currentTimeMillis()-startTimeMil)); } }
3).对比结果
呵呵,看看结果,还是挺吓人的
四.Google Protobuf编解码
Protobuf是一个灵活、高效、结构化的数据序列化架构,相比于XML等传统的序列化工具,他更小、更快、更简单。Protobuf支持数据结构化一次即可到处使用,甚至跨语 言,通过代码生成工具可以自动生成不同语言版本的源代码,甚至可以使用不同版本的数据结构进程间进行数据传递,实现数据结构的向前兼容。
1). 下载Protobuf地址
http://download.csdn.net/detail/dfdsggdgg/9507327
2).编写.proto文件
package com.leehongee.netserver.net.bean;option java_package = "com.phei.netty.protobuf";option java_outer_classname = "UserInfo"; message User{ required int32 userID = 1; required string userName = 2; }
3).CMD命令编译.proto文件
D:\protobuf\protobuf-2.5.0>protoc.exe --java_out=./ hello.proto
命令执行后,在目录com\leehongee\netserver\net\bean 目录下将生成一个.java源文件。
4).工程引入protobuf-java-2.5.0.jar,再将刚才生成的.java文件放入对应的包目录下,编写测试类
package com.phei.netty.protobuf;import java.io.IOException;import com.google.protobuf.InvalidProtocolBufferException;public class UserInfoTest {private static byte[] encode(UserInfo.User user){return user.toByteArray();}/** * 反序列化 * @param body * @return * @throws InvalidProtocolBufferException */private static UserInfo.User decode(byte[] body) throws InvalidProtocolBufferException{return UserInfo.User.parseFrom(body);}/** * 序列化 * @return */private static UserInfo.User createUser(){UserInfo.User.Builder builder = UserInfo.User.newBuilder();builder.setUserID(666666);builder.setUserName("hello world");return builder.build();} public static void main(String[] args) throws IOException {UserInfo.User user = createUser();System.out.println("protobuf序列化后字节流大小"+user.toByteArray().length);System.out.println("Before encode : "+ user.toString());System.out.println(encode(user).length);UserInfo.User user2 = decode(encode(user)); System.out.println("After decode : "+ user.toString());}}
5).测试结果
五.MessagePack编解码
MessagePack是一个高效的二进制序列化框架,它像JSON一样支持不同的语言的数据交换,但是他的性能更快,序列化后的流更小。
1). 下载MessagePack jar包
http://download.csdn.net/detail/dfdsggdgg/9507386
2).编写测试类
UserInfo类
</pre><pre name="code" class="java">package com.phei.netty.messagepack;import org.msgpack.annotation.Message;@Messagepublic class UserInfo{ public String userName; public int userID; }
UserInfoTest类
package com.phei.netty.messagepack;import java.io.IOException;import org.msgpack.MessagePack;public class UserInfoTest { public static void main(String args[]) throws IOException{ UserInfo user = new UserInfo(); user.userID=666666; user.userName="hello world"; MessagePack pack = new MessagePack(); //序列化 byte[] bytes = pack.write(user); System.out.println("MessagePack序列化后字节流大小:"+bytes.length); //反序列化 UserInfo u = pack.read(bytes, UserInfo.class); System.out.println("DeviceID: "+u.userName); } }
3).测试结果
1 0
- java编解码技术
- 十、编解码技术--Java序列化
- Netty编解码技术
- 九、编解码技术
- 编解码技术
- java网络编程之Netty编解码技术(六)
- Java:Base64编解码
- Java中的编解码
- Java的编解码
- Java Base64编解码
- java web 编解码
- java编解码base64
- BASE-64编/解码技术
- 视频编解码技术小结
- 编解码技术学习网站
- Netty初探-编解码技术
- 视频编解码技术介绍
- java中的编解码问题
- 飞机最短里程
- iOS 开发中的注意事项
- 南阳1132
- Android一句话 | ViewGroup事件分发
- CSS选择器优先级计算
- java编解码技术
- 什么叫内存屏障、编译屏障、内存对齐
- 改变myeclipse背景颜色
- HDU_1245_Saving James Bond_最短路
- Java基本概念
- android Criteria
- Android的Depth-LIB-Android的使用
- 【Linux开发技术之常见问题】一个建立线程时常见的问题:invalid conversion from `void*' to `void*(*)(void*)
- 深度优先搜索