google protocol buffers

宋烨烁
2023-12-01

protocol buffers 简称 ProtoBuf

一、简介

  官方文档:https://developers.google.com/protocol-buffers/docs/proto3
  源码:https://github.com/protocolbuffers/protobuf
  参考博客:https://www.jianshu.com/p/b33ca81b19b5

官方描述:

1.protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于通信协议、数据存储等。

2.protocol buffers是一种灵活,高效,自动化机制的结构化数据序列化方法,可以类比XML,但是比XML更小、更快、更为简单。

3.你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏旧数据结构编译而成并且已经部署的程序。

总结:序列化结构数据的方法,有以下特点:

  • 语言无关、平台无关
  • 高效。比XML更小、更快、更为简单
  • 拓展性、兼容性好。可以更新数据结构而不影响和破坏原有的旧程序。

序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

序列化的目的:

1.以某种存储形式使自定义对象持久化

2.将对象从一个地方传递到另一个地方

3.使程序更具有维护性

二、使用ProtoBuf3

1.ProtocBuf安装

# Ubantu下安装Protocbuf
sudo snap install protobuf --classic
sudo apt  install protobuf-compiler
# 测试
xiao@xiao:~$ protoc --version
libprotoc 3.0.0

3.proto文件编写

第一步,创建 .proto 文件,定义数据结构

第二步,protoc 编译 .proto 文件生成读写接口

第三步,调用接口实现序列化、反序列化以及读写

4.proto编译说明

protoc --proto_path=IMPORT_PATH  --java_out=DST_DIR  path/to/file.proto

–proto_path:相当于-I,IMPORT_PATH指定.proto解析import指令时查找文件的目录。如果省略,则使用当前目录。

–java_out:其后边是输出java代码的路径

path/to/file.proto: 指定在这个路径下的file.protoc文件

三、android中的使用

  在Telephony中google使用此工具来序列化eccdata.txt文件以及解析eccdata

1.protobuf_ecc_data.proto文件

google protobuf_ecc_data.prpto文件 代码如下:

syntax = "proto2";

package ecc;

option java_package = "com.android.phone.ecc";
option java_outer_classname = "ProtobufEccData";

// EccInfo represents an Emergency Call Code (i.e. an emergency phone
// number such as 911, 112, ...)
message EccInfo {
    enum Type {
        TYPE_UNSPECIFIED = 0;
        POLICE = 1;
        AMBULANCE = 2;
        FIRE = 3;
    }

    // Required: Every EccInfo shall contain a phone number.
    optional string phone_number = 1;

    // Extra rules: Every Ecc should have at least 1 valid type.
    repeated Type types = 2 [packed=true];
}

// CountryInfo represents available ECCs of a country/region, recognized
// with ISO country code.
message CountryInfo {
    // Required: Every CountryInfo shall contain a ISO country code.
    optional string iso_code = 1;

    // Extra rules: There should be at least one EccInfo in this list.
    repeated EccInfo eccs = 2;

    // Required: Every CountryInfo shall contain a fallback number, shall
    // be either 112 or 911.
    //
    // If an emergency number in EccInfo is declined by ril.ecclist, this
    // fallback number may take the place.
    //
    // Per http://www.etsi.org/deliver/etsi_ts/122100_122199/122101/09.01.00_60/ts_122101v090100p.pdf,
    // 112 and 911 shall always be available.
    optional string ecc_fallback = 3;
}

message AllInfo {
    // The revision value in ecc/input/eccdata.json should be increased
    // before releasing a new content.
    //
    // This field is not used to compare data revision for online updating.
    // It's reserved for identifying ecc info problems.
    optional int32 revision = 1;

    // Extra rules: There should be at least one CountryInfo in this list.
    repeated CountryInfo countries = 2;
}

其要序列化的数据格式如下:

revision: 2
countries {
  iso_code: "AD"
  eccs {
    phone_number: "110"
    types: POLICE
  }
  eccs {
    phone_number: "118"
    types: FIRE
  }
  ecc_fallback: "112"
}

google 利用如下方法,将eccdata编码成raw的文件

#!/bin/bash
# 编码
aprotoc --encode=ecc.AllInfo proto/protobuf_ecc_data.proto \
  < "eccdata.txt" > "${eccdata.raw}"
# 解码 - 根据文档模仿 google 写一个解码的命令,如下:
aprotoc --decode=ecc.AllInfo proto/protobuf_ecc_data.proto \
 < "${eccdata.raw}" > "ap.txt"

–encode=MESSAGE_TYPE Read a text-format message of the given type
from standard input and write it in binary
to standard output. The message type must
be defined in PROTO_FILES or their imports.

–encode=MESSAGE_TYPE 读取给定类型的文本格式消息
从标准输入并将其以二进制形式写入
标准输出。消息类型必须
在 PROTO_FILES 或其导入中定义。

最后使用protoc文件编译生成的 ProtobufEccData接口,调用启动的AllInfo.parseFrom来在运行时获取数据。

 类似资料:

相关阅读

相关文章

相关问答