使用Protobuf备份数据
· 阅读需 2 分钟
一个高效的序列化工具来备份数据,Protobuf 是一个不错的选择!
开源地址:https://github.com/protocolbuffers/protobuf
安装protoc工具
首先安装Protobuf的工具,我使用的macbook,可以使用Homebrew安装。
brew install protobuf
安装完毕后验证:
protoc --version
libprotoc 3.21.5
定义描述文件
我使用的java,springboot工程。首先引入依赖
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
定义描述文件,例如 Asset.proto
syntax = "proto3";
option java_package = "com.seatone.parse.proto";
option java_outer_classname = "AssetProto";
message Asset {
string id = 1;
string name = 2;
string standardTypeCode = 3;
}
然后使用工具生成对应的实体。
第一个参数为输出目录,第二个参数为描述文件。
protoc --java_out=./src/main/java/ ./src/main/resources/proto/Asset.proto
这样我们就可以利用这个对象来进行序列化和反序列化。
序列化和反序列化
@Test
public void protoToByteArray() throws InvalidProtocolBufferException {
byte[] byteArray = AssetProto.Asset.newBuilder()
.setId("l9L4T1Hps7tlses66AU")
.setName("abc")
.setStandardTypeCode("50101")
.build()
.toByteArray();
System.out.println(Arrays.toString(byteArray));
AssetProto.Asset asset = AssetProto.Asset.parseFrom(byteArray);
System.out.println(asset);
}
写入和读取文件
定义写入文件方法
/**
* 备份方法,流式写入 + GZIP
*/
public static void backupStream(List<?> data, String filePath) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT, false);
try (GZIPOutputStream gzip =
new GZIPOutputStream(new BufferedOutputStream(Files.newOutputStream(Paths.get(filePath))))) {
mapper.writeValue(gzip, data);
}
}
定义还原文件方法
/**
* 还原方法
*/
public static <T> T restore(String filePath, Class<T> type) throws IOException {
ObjectMapper mapper = new ObjectMapper();
try (GZIPInputStream gzip = new GZIPInputStream(Files.newInputStream(Paths.get(filePath)))) {
if (type.equals(List.class)) {
JavaType javaType = mapper.getTypeFactory().constructCollectionType(List.class, byte[].class);
return mapper.readValue(gzip, javaType);
} else {
return mapper.readValue(gzip, type);
}
}
}
最终:备份和还原数据
/**
* 备份数据到文件
*/
@Test
public void backupAsset() throws IOException {
List<byte[]> byteList = Lists.newArrayList(AssetProto.Asset.newBuilder()
.setId("l9L4T1Hps7tlses66AU")
.setName("abc")
.setStandardTypeCode("50101")
.build()
.toByteArray()
);
backupStream(byteList, backup_path);
}
/**
* 从文件还原数据
*/
@Test
public void restoreAsset() throws IOException {
List<byte[]> restore = restore(backup_path, List.class);
for (byte[] bytes : restore) {
AssetProto.Asset asset = AssetProto.Asset.parseFrom(bytes);
System.out.println(asset);
}
}
谷歌出品,稳定和效率都值得肯定!
