您现在的位置是:首页 > 文章详情

Proto3序列化数到文件与反序列化

日期:2020-03-20点击:490

proto3序列化很好用,在原来开发APP存数据到日志时,日志文档半小时可达300M,数据量大时对性能有很大影响,因此改用proto序列化存储数据,经测试性能有所提升,日志大小为原来三分之一,所以优势还是很明显的。

但proto3序列化多条消息到文件时,按官方文档介绍,反序列化时是没法区分一个完整对象序列化数据的界限的,也就是没有分隔符,因此需要自己设定分隔符,反序列化时按规则解即可,以下是基于上一篇文章中环境的案例

一、多消息持续序列化规则

每个对象序列化后字节数的长度作为序列化内容前置4个字节的数据,即若一条序列化数据长度为100个字节,那么前这个数据前加4个字节,这4个字节的内容是100,那么总长度就是104个字节,依此规则持续序列化到文件即可

二、定义proto数据结构

syntax = "proto3"; package tutorial; message Person { string name = 1; int32 id = 2; string email = 3; string phone = 4; } 

三、序列化测试

/** * 序列化 * * @param path */ private void serializeProto(String path) { System.out.println("serialize file " + path); try { OutputStream outputStream = new FileOutputStream(new File(path)); byte[] data; for (int i = 0; i < 10; i++) { Message.Person person = Message.Person.newBuilder().setId(i) .setEmail(String.valueOf(i)).setName(String.valueOf(i)).setPhone(String.valueOf(i)).build(); byte[] dataByte = person.toByteArray(); byte[] lenByte = ProtoHelper.intToByteArray(dataByte.length); data = new byte[dataByte.length + lenByte.length]; System.arraycopy(lenByte, 0, data, 0, lenByte.length); System.arraycopy(dataByte, 0, data, lenByte.length, dataByte.length); outputStream.write(data); System.out.println("serialize len :" + dataByte.length + ",id:" + person.getId() + ",name:" + person.getName() + ",email:" + person.getEmail() + ",phone:" + person.getPhone()); } outputStream.flush(); outputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

四、反序列化

因为上述数据量小,这里一次性从文件读出来,就没有设置缓冲区了

/** * 反序列化 * @param path */ public void deSerializeProto(String path) { System.out.println("deSerialize file " + path); try { InputStream inputStream = new FileInputStream(new File(path)); byte[] data = new byte[4096]; int len = 0; while ((len = inputStream.read(data)) > 0) { int index = 0; while (index < len) { byte[] lenByte = new byte[4]; System.arraycopy(data, index, lenByte, 0, 4); int itemLen = ProtoHelper.byteArrayToInt(lenByte); byte[] dataByte = new byte[itemLen]; System.arraycopy(data, index + lenByte.length, dataByte, 0, itemLen); Message.Person person = Message.Person.parseFrom(dataByte); System.out.println("deSerialize len :" + (dataByte.length + 4) + ",id:" + person.getId() + ",name:" + person.getName() + ",email:" + person.getEmail() + ",phone:" + person.getPhone()); index = index + lenByte.length + dataByte.length; } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

执行结果:
screenshot

由于proto跨平台,所以java端序列化后,C端同事也能解码文件,有一定的日志安全性吧

原文链接:https://yq.aliyun.com/articles/750884
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章