Protobuf:一种轻量级、高效的数据交换格式,附Java与Python数据交换示例

简介: Protobuf:一种轻量级、高效的数据交换格式,附Java与Python数据交换示例

目录

下载安装Protobuf

定义数据格式

Java代码序列化

Python反序列化

Protobuf(Protocol Buffers)是由 Google 开发的一种轻量级、高效的数据交换格式


官方文档:https://protobuf.dev/overview/

GitHub:https://github.com/protocolbuffers/protobuf

https://github.com/protocolbuffers/protobuf/releases/latest

VSCode语法高亮插件:vscode-proto

本文仅做一个简单的代码演示,并不涉及原理说明


本文演示如何将Java数据通过文件的方式传递给Python


9682c201b800da6799bd08792964858f_eb7966630daf4613bc3e19d9fb7b8602.png

项目结构


protobuf-demo/

 protobuf-data        # 定义通用的数据结构

 protobuf-java        # Java项目序列化protobuf

 protobuf-python      # Python项目反序列化protobuf


下载安装Protobuf

# 检查系统版本

$ sw_vers

ProductName:    Mac OS X

ProductVersion: 10.14.4

BuildVersion:   18E2035


# 下载解压 protoc-23.0-osx-x86_64.zip


$ ./bin/protoc --version

libprotoc 23.0


定义数据格式

protobuf-data/addressbook.proto


// 文件:addressbook.proto


// 指定 Protobuf 版本为版本3

syntax = "proto3";

// 指定 protobuf 包名,防止有相同类名的 message 定义

package com.example.protobuf;

// 是否生成多个文件

option java_multiple_files = true;

// 生成的文件存放在哪个包下

option java_package = "com.example.protobuf";

// 生成的类名,如果没有指定,会根据文件名自动转驼峰来命名

option java_outer_classname = "AddressBookProtos";


message Person {

 // =1,=2 作为序列化后的二进制编码中的字段的唯一标签,也因此,1-15 比 16 会少一个字节,所以尽量使用 1-15 来指定常用字段。

 optional int32 id = 1;

 optional string name = 2;

 optional string email = 3;


 enum PhoneType {

   MOBILE = 0;

   HOME = 1;

   WORK = 2;

 }


 message PhoneNumber {

   optional string number = 1;

   optional PhoneType type = 2;

 }


 repeated PhoneNumber phones = 4;

}


message AddressBook {

 repeated Person people = 1;

}



使用 Protobuf 提供的编译器,可以将 .proto 文件编译成各种语言的代码文件(如 Java、C++、Python 等)。


572bf2f9c894b44ad13db87b195fea06_1760c47412b84ac2988e33595c3aaa3d.png

Java代码序列化

依赖


<dependency>

   <groupId>com.google.protobuf</groupId>

   <artifactId>protobuf-java</artifactId>

   <version>3.22.3</version>

</dependency>


生成java代码


./bin/protoc --java_out=../protobuf-java/src/main/java ./addressbook.proto

1

项目结构


$ tree

.

├── pom.xml

├── protobuf-java.iml

└── src

   ├── main

   │   └── java

   │       └── com

   │           └── example

   │               └── protos

   │                   ├── AddressBook.java

   │                   ├── AddressBookOrBuilder.java

   │                   ├── AddressBookProtos.java

   │                   ├── Person.java

   │                   └── PersonOrBuilder.java

   └── test

       └── java

           └── com

               └── example


构建测试


package com.example;


import com.example.protos.AddressBook;

import com.example.protos.Person;

import org.junit.Test;


public class ProtobufTest {

   @Test

   public void testBuildProtobuf(){

       //  构建

       AddressBook addressBook = AddressBook

               .newBuilder()

               .addPeople(Person.newBuilder()

                       .setId(2)

                       .setName("小明")

                       .setEmail("yyds@126.com")

                       .addPhones(Person.PhoneNumber.newBuilder()

                               .setNumber("18388888888")

                               .setType(Person.PhoneType.HOME)

                       )

               )

               .build();

       System.out.println(addressBook);

   }

}



输出


people {

 id: 2

 name: "\345\260\217\346\230\216"

 email: "yyds@126.com"

 phones {

   number: "18388888888"

   type: HOME

 }

}



序列化


// 序列化成字节数组

byte[] byteArray = addressBook.toByteArray();

// 反序列化 - 字节数组转对象

AddressBook addressBook2 = AddressBook.parseFrom(byteArray);

System.out.println("字节数组反序列化:");

System.out.println(addressBook2);


// 序列化到文件

addressBook.writeTo(new FileOutputStream("AddressBook.txt"));

// 读取文件反序列化

AddressBook addressBook3 = AddressBook.parseFrom(new FileInputStream("AddressBook.txt"));

System.out.println("文件读取反序列化:");

System.out.println(addressBook3);


AddressBook.txt



)小明yyds@126.com"

18388888888


Python反序列化

安装依赖


pip install protobuf


生成Python代码


./bin/protoc --python_out=../protobuf-python ./addressbook.proto


目录


$ tree -I venv

.

├── AddressBook.txt            # 由上一步java代码输出的数据文件

├── addressbook_pb2.py         # 自动生成的文件

└── demo.py


反序列化示例 demo.py


# -*- coding: utf-8 -*-

"""

@File    : demo.py

@Date    : 2023-05-12

"""

import addressbook_pb2


if __name__ == '__main__':

   # 反序列化

   with open('AddressBook.txt', 'rb') as f:

       addressBook = addressbook_pb2.AddressBook()

       addressBook.ParseFromString(f.read())



       for person in addressBook.people:

           print(person.name)

           # 小明


直接打印addressBook对象


people {

 id: 2

 name: "\345\260\217\346\230\216"

 email: "yyds@126.com"

 phones {

   number: "18388888888"

   type: HOME

 }

}



Python的体验不是很好,代码提示的能力基本为零,需要使用dir(obj)查看对象属性才知道


完整代码:https://github.com/mouday/protobuf-demo


参考

Protobuf: 高效数据传输的秘密武器

Python使用protobuf序列化和反序列化

————————————————

版权声明:本文为CSDN博主「彭世瑜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/mouday/article/details/130639021

相关文章
|
25天前
|
存储 Java API
【Azure 存储服务】Java Storage SDK 调用 uploadWithResponse 代码示例(询问ChatGTP得代码原型后人力验证)
【Azure 存储服务】Java Storage SDK 调用 uploadWithResponse 代码示例(询问ChatGTP得代码原型后人力验证)
|
1月前
|
消息中间件 负载均衡 Java
"深入Kafka核心:探索高效灵活的Consumer机制,以Java示例展示数据流的优雅消费之道"
【8月更文挑战第10天】在大数据领域,Apache Kafka凭借其出色的性能成为消息传递与流处理的首选工具。Kafka Consumer作为关键组件,负责优雅地从集群中提取并处理数据。它支持消息的负载均衡与容错,通过Consumer Group实现消息的水平扩展。下面通过一个Java示例展示如何启动Consumer并消费数据,同时体现了Kafka Consumer设计的灵活性与高效性,使其成为复杂消费场景的理想选择。
80 4
|
25天前
|
JSON Java API
【Azure API 管理】通过Java APIM SDK创建一个新的API,如何为Reqeust的Representation设置一个内容示例(Sample)?
【Azure API 管理】通过Java APIM SDK创建一个新的API,如何为Reqeust的Representation设置一个内容示例(Sample)?
|
1月前
|
缓存 Java 数据处理
|
1月前
|
设计模式 存储 Java
掌握Java设计模式的23种武器(全):深入解析与实战示例
掌握Java设计模式的23种武器(全):深入解析与实战示例
|
1月前
|
Java
Java模拟文件发送给服务器,服务器将文件转发给其他用户,并保存到服务器本地,其他用户可以接收,并保存到本地磁盘,支持各种文件格式,并解决通信中服务器怎么区分客户端发来的文件类型
Java模拟文件发送给服务器,服务器将文件转发给其他用户,并保存到服务器本地,其他用户可以接收,并保存到本地磁盘,支持各种文件格式,并解决通信中服务器怎么区分客户端发来的文件类型
|
1月前
|
存储 缓存 监控
Java本地高性能缓存实践问题之在EncacheTest示例中正确移除一个缓存实例的问题如何解决
Java本地高性能缓存实践问题之在EncacheTest示例中正确移除一个缓存实例的问题如何解决
|
2月前
|
Java 编译器 开发者
Java演进问题之Truffle处理不同编程语言的源代码或中间格式如何解决
Java演进问题之Truffle处理不同编程语言的源代码或中间格式如何解决
|
2月前
|
前端开发 JavaScript UED
Python Web应用中的WebSocket实战:前后端分离时代的实时数据交换
【7月更文挑战第16天】在前后端分离的Web开发中,WebSocket解决了实时数据交换的问题。使用Python的Flask和Flask-SocketIO库,后端创建WebSocket服务,监听并广播消息。前端HTML通过JavaScript连接到服务器,发送并显示接收到的消息。WebSocket适用于实时通知、在线游戏等场景,提升应用的实时性和用户体验。通过实战案例,展示了如何实现这一功能。
243 2
|
1月前
|
消息中间件 数据库 开发者