Spring-Boot -- Java对象的序列化(反序列化)+ GZIP实现字节数组的压缩和解压缩
一、Pom
<!-- https://mvnrepository.com/artifact/net.lecousin.compression/gzip -->
<dependency>
<groupId>net.lecousin.compression</groupId>
<artifactId>gzip</artifactId>
<version>0.1.5</version>
</dependency>
假如我们知道有gzip这个东西,但是我们不知道如何在我们的pom文件中依赖的话,我们可以打开如下地址进行相应的查询
Maven官网 : 点击打开链接
1.搜索
2.选择版本
3.查看在maven项目中如何添加依赖,当然,还支持Gradle等其他的依赖方式
二、应用场景
有一批数据存在于文件中,需要被封装成对象,而对象才是我们在Java中实实在在需要的东西,而这些数据很大,且对象的构建,需要长期引用文件里面的数据,怎么办? 不可能构建一个对象就读取一次文件吧,如果对象是亿万级别的,那每次读取文件将是非常耗费IO资源的,因此,我们最好的做法,就是一次性将文件里面的数据读取到内存中,基于内存的操作是非常快速的,因此,我们想用redis来做缓存数据的媒介,因为,它也是基于内存操作的,而且还是key-value键值对,因此,访问是很方便的
redis的 key 和 value 支持 byte[]的写入和读取,为了就是存储对象,因为我们知道,Java中存储对象,我们可以利用集合List或者Set亦或者HashTable来存储,但是在redis中,想要存储对象,必须先序列化对象,反之,读取的时候,在将对象反序列化还原即可
由于redis也是要消耗内存的,因此,为了最大程度的压缩对象,节约内存开销,我们采用gizp压缩序列化后的对象,相比直接序列化对象存储在redis中,压缩后的性能要比前者高了好几倍甚至是十倍以上(具体看对象的大小,对象如果小的话,序列化就行,如果这时候再用gizp压缩的话,会适得其反,小的对象序列化后再压缩反而比之前没压缩时占的内存要大的多)
好了,开干
三、两个工具-- 序列化(反序列化)+压缩(解压缩)
(1)SerializeUtil.java
package com.appleyk.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializeUtil {
public static byte[] serialize(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
// 序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
System.err.println(e.getMessage());
}
return null;
}
public static Object unserialize(byte[] bytes) {
ByteArrayInputStream bais = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
System.err.println(e.getMessage());
}
return null;
}
}
(2)CompressUtil.java -- 注意代码中,资源一定要从头到尾,从上到下释放
package com.appleyk.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class CompressUtil {
public static byte[] writeCompressObject(Object object){
byte[] data = null;
try{
//建立字节数组输出流
ByteArrayOutputStream bao = new ByteArrayOutputStream();
GZIPOutputStream gzout = new GZIPOutputStream(bao);
ObjectOutputStream out = new ObjectOutputStream(gzout);
out.writeObject(object);
out.flush();
out.close();
gzout.close();
data = bao.toByteArray();
bao.close();
}catch(IOException e){
System.err.println(e);
}
return data;
}
public static Object readCompressObject(byte[] data){
Object object = null;
try{
//建立字节数组输入流
ByteArrayInputStream i = new ByteArrayInputStream(data);
//建立gzip解压输入流
GZIPInputStream gzin=new GZIPInputStream(i);
//建立对象序列化输入流
ObjectInputStream in = new ObjectInputStream(gzin);
//按制定类型还原对象
object = in.readObject();
}catch(ClassNotFoundException e){
System.err.println(e.getMessage());
}catch (IOException ex) {
System.err.println(ex);
}
return object;
}
}
四、测试
(1)gzipTest.java
package com.appleyk.Test;
import java.io.Serializable;
import org.junit.Test;
import com.appleyk.utils.CompressUtil;
import com.appleyk.utils.SerializeUtil;
class Node implements Serializable {
private long id;
private double x;
private double y;
private String tag;
public Node(long id,double x,double y,String tag) {
this.id = id;
this.x = x;
this.y = y;
this.tag = tag;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
}
public class gzipTest {
@Test
public void Test01(){
Node node = new Node(112231L, 65.2121412, 120.365412, "OsmNode:Parkdasdasdasdasdasdasdadasdasdadasdasdasdasdasdasdasdasdasdasdasdasdsaaaaaaaa");
System.err.println("对象序列化后占 :"+SerializeUtil.serialize(node).length+"字节");
System.err.println("对象序列化加压缩后占:"+CompressUtil.writeCompressObject(node).length+"字节");
Node node2 = (Node)CompressUtil.readCompressObject(CompressUtil.writeCompressObject(node));
System.err.println("对象解压缩后获取标签元素:"+node2.getTag());
}
}
(2)如果tag内容比较大的话,对比如下
(3)如果tag内存较少的话,对比如下
(4)随着对象越大,gzip的优势就越明显,这个不再演示
最后,就是结合redis进行key和value的写入了,这部分也比较简单,就不做演示了,有问题留言,欢迎一起讨论!
上一篇: rsync常用的三种用法