Google Protocol Buffer入门

简介

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。

Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。

如果你在开发中使用过常用的数据交换格式如xml、json,那么protocol buffer也不是什么神奇的东西了,它和xml、json类似,也可以作为开发中的一种数据交换格式,只不过相较xml和json,protocol buffer的优点更明显,它更小、更快、更简单。

windows下使用Protobuf

对于非C++用户,可以直接下载官网预编译好的protoc.exe(install the protocol compiler is to download a pre-built binary):

https://repo1.maven.org/maven2/com/google/protobuf/protoc/

对于C++用户,可以下载源码编译生成proto.exe。

Java中使用ProtocolBuffer

在Java中使用ProtocolBuffer的步骤大致分为下面这几点:

  • (1)编写.proto文件,定义消息类型

application.proto

syntax = "proto2";
package proto;
option java_package = "com.ziyun.bean.proto";
option java_outer_classname = "IpAddress";
message ip_address {
optional string af = 1;
optional string addr = 2;
}
  • (2)使用ProtocolBuffer的编译器(protoc.exe),将.proto文件编译成对应的java文件.

    生成java对象的通用工具类
public class GenereteBeanUtil {

    /**
* 通过执行cmd命令调用protoc.exe程序
* 参考命令:protoc2.exe -I=./ --java_out=./ ./proto/access_point.proto
*
* @param absolutePath exe程序绝对路径
* @param protoFileName proto文件名
*/
public static void generateBean(String absolutePath, String protoFileName) {
String[] cmd = {absolutePath + "protoc2.exe", "-I=" + absolutePath, "--java_out=" + absolutePath,
absolutePath + "proto/" + protoFileName};
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException e) {
e.printStackTrace();
}
} public static void main(String[] args) throws IOException {
File directory = new File("");
String absolutePath = directory.getAbsolutePath(); //proto文件路径
String protoPath = absolutePath + File.separator + "zy-libs" + File.separator + "zy-zeromq"
+ File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator +
"proto" + File.separator;
String dirPath = absolutePath + File.separator + "zy-libs" + File.separator + "zy-zeromq" + File.separator +
"src" + File.separator + "main" + File.separator + "java" + File.separator; File dir = new File(protoPath);
File[] files = dir.listFiles();
for (File file : files) {
String fileName = file.getName();
GenereteBeanUtil.generateBean(dirPath, fileName);
}
}
}

通过工具类生成的java对象

// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: proto/ip_address.proto package com.ziyun.bean.proto; public final class IpAddress {
private IpAddress() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
}
public interface ip_addressOrBuilder extends
// @@protoc_insertion_point(interface_extends:proto.ip_address)
com.google.protobuf.MessageOrBuilder { /**
* <code>optional string af = 1;</code>
*/
boolean hasAf();
/**
* <code>optional string af = 1;</code>
*/
java.lang.String getAf();
/**
* <code>optional string af = 1;</code>
*/
com.google.protobuf.ByteString
getAfBytes(); /**
* <code>optional string addr = 2;</code>
*/
boolean hasAddr();
/**
* <code>optional string addr = 2;</code>
*/
java.lang.String getAddr();
/**
* <code>optional string addr = 2;</code>
*/
com.google.protobuf.ByteString
getAddrBytes();
}
/**
* Protobuf type {@code proto.ip_address}
*/
public static final class ip_address extends
com.google.protobuf.GeneratedMessage implements
// @@protoc_insertion_point(message_implements:proto.ip_address)
ip_addressOrBuilder {
// Use ip_address.newBuilder() to construct.
private ip_address(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
super(builder);
this.unknownFields = builder.getUnknownFields();
}
private ip_address(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } private static final ip_address defaultInstance;
public static ip_address getDefaultInstance() {
return defaultInstance;
} public ip_address getDefaultInstanceForType() {
return defaultInstance;
} private final com.google.protobuf.UnknownFieldSet unknownFields;
@java.lang.Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return this.unknownFields;
}
private ip_address(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
initFields();
int mutable_bitField0_ = 0;
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder();
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
default: {
if (!parseUnknownField(input, unknownFields,
extensionRegistry, tag)) {
done = true;
}
break;
}
case 10: {
com.google.protobuf.ByteString bs = input.readBytes();
bitField0_ |= 0x00000001;
af_ = bs;
break;
}
case 18: {
com.google.protobuf.ByteString bs = input.readBytes();
bitField0_ |= 0x00000002;
addr_ = bs;
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
e.getMessage()).setUnfinishedMessage(this);
} finally {
this.unknownFields = unknownFields.build();
makeExtensionsImmutable();
}
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return IpAddress.internal_static_proto_ip_address_descriptor;
} protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return IpAddress.internal_static_proto_ip_address_fieldAccessorTable
.ensureFieldAccessorsInitialized(
IpAddress.ip_address.class, IpAddress.ip_address.Builder.class);
} public static com.google.protobuf.Parser<ip_address> PARSER =
new com.google.protobuf.AbstractParser<ip_address>() {
public ip_address parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return new ip_address(input, extensionRegistry);
}
}; @java.lang.Override
public com.google.protobuf.Parser<ip_address> getParserForType() {
return PARSER;
} private int bitField0_;
public static final int AF_FIELD_NUMBER = 1;
private java.lang.Object af_;
/**
* <code>optional string af = 1;</code>
*/
public boolean hasAf() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
/**
* <code>optional string af = 1;</code>
*/
public java.lang.String getAf() {
java.lang.Object ref = af_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
af_ = s;
}
return s;
}
}
/**
* <code>optional string af = 1;</code>
*/
public com.google.protobuf.ByteString
getAfBytes() {
java.lang.Object ref = af_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
af_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
} public static final int ADDR_FIELD_NUMBER = 2;
private java.lang.Object addr_;
/**
* <code>optional string addr = 2;</code>
*/
public boolean hasAddr() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
/**
* <code>optional string addr = 2;</code>
*/
public java.lang.String getAddr() {
java.lang.Object ref = addr_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
addr_ = s;
}
return s;
}
}
/**
* <code>optional string addr = 2;</code>
*/
public com.google.protobuf.ByteString
getAddrBytes() {
java.lang.Object ref = addr_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
addr_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
} private void initFields() {
af_ = "";
addr_ = "";
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false; memoizedIsInitialized = 1;
return true;
} public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeBytes(1, getAfBytes());
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeBytes(2, getAddrBytes());
}
getUnknownFields().writeTo(output);
} private int memoizedSerializedSize = -1;
public int getSerializedSize() {
int size = memoizedSerializedSize;
if (size != -1) return size; size = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(1, getAfBytes());
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(2, getAddrBytes());
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
} private static final long serialVersionUID = 0L;
@java.lang.Override
protected java.lang.Object writeReplace()
throws java.io.ObjectStreamException {
return super.writeReplace();
} public static IpAddress.ip_address parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static IpAddress.ip_address parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static IpAddress.ip_address parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static IpAddress.ip_address parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static IpAddress.ip_address parseFrom(java.io.InputStream input)
throws java.io.IOException {
return PARSER.parseFrom(input);
}
public static IpAddress.ip_address parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return PARSER.parseFrom(input, extensionRegistry);
}
public static IpAddress.ip_address parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return PARSER.parseDelimitedFrom(input);
}
public static IpAddress.ip_address parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return PARSER.parseDelimitedFrom(input, extensionRegistry);
}
public static IpAddress.ip_address parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return PARSER.parseFrom(input);
}
public static IpAddress.ip_address parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return PARSER.parseFrom(input, extensionRegistry);
} public static Builder newBuilder() { return Builder.create(); }
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder(IpAddress.ip_address prototype) {
return newBuilder().mergeFrom(prototype);
}
public Builder toBuilder() { return newBuilder(this); } @java.lang.Override
protected Builder newBuilderForType(
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* Protobuf type {@code proto.ip_address}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:proto.ip_address)
IpAddress.ip_addressOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return IpAddress.internal_static_proto_ip_address_descriptor;
} protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return IpAddress.internal_static_proto_ip_address_fieldAccessorTable
.ensureFieldAccessorsInitialized(
IpAddress.ip_address.class, IpAddress.ip_address.Builder.class);
} // Construct using com.ziyun.bean.proto.IpAddress.ip_address.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
} private Builder(
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
}
}
private static Builder create() {
return new Builder();
} public Builder clear() {
super.clear();
af_ = "";
bitField0_ = (bitField0_ & ~0x00000001);
addr_ = "";
bitField0_ = (bitField0_ & ~0x00000002);
return this;
} public Builder clone() {
return create().mergeFrom(buildPartial());
} public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return IpAddress.internal_static_proto_ip_address_descriptor;
} public IpAddress.ip_address getDefaultInstanceForType() {
return IpAddress.ip_address.getDefaultInstance();
} public IpAddress.ip_address build() {
IpAddress.ip_address result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
} public IpAddress.ip_address buildPartial() {
IpAddress.ip_address result = new IpAddress.ip_address(this);
int from_bitField0_ = bitField0_;
int to_bitField0_ = 0;
if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
to_bitField0_ |= 0x00000001;
}
result.af_ = af_;
if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
to_bitField0_ |= 0x00000002;
}
result.addr_ = addr_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
} public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof IpAddress.ip_address) {
return mergeFrom((IpAddress.ip_address)other);
} else {
super.mergeFrom(other);
return this;
}
} public Builder mergeFrom(IpAddress.ip_address other) {
if (other == IpAddress.ip_address.getDefaultInstance()) return this;
if (other.hasAf()) {
bitField0_ |= 0x00000001;
af_ = other.af_;
onChanged();
}
if (other.hasAddr()) {
bitField0_ |= 0x00000002;
addr_ = other.addr_;
onChanged();
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
} public final boolean isInitialized() {
return true;
} public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
IpAddress.ip_address parsedMessage = null;
try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
parsedMessage = (IpAddress.ip_address) e.getUnfinishedMessage();
throw e;
} finally {
if (parsedMessage != null) {
mergeFrom(parsedMessage);
}
}
return this;
}
private int bitField0_; private java.lang.Object af_ = "";
/**
* <code>optional string af = 1;</code>
*/
public boolean hasAf() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
/**
* <code>optional string af = 1;</code>
*/
public java.lang.String getAf() {
java.lang.Object ref = af_;
if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
af_ = s;
}
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>optional string af = 1;</code>
*/
public com.google.protobuf.ByteString
getAfBytes() {
java.lang.Object ref = af_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
af_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>optional string af = 1;</code>
*/
public Builder setAf(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000001;
af_ = value;
onChanged();
return this;
}
/**
* <code>optional string af = 1;</code>
*/
public Builder clearAf() {
bitField0_ = (bitField0_ & ~0x00000001);
af_ = getDefaultInstance().getAf();
onChanged();
return this;
}
/**
* <code>optional string af = 1;</code>
*/
public Builder setAfBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000001;
af_ = value;
onChanged();
return this;
} private java.lang.Object addr_ = "";
/**
* <code>optional string addr = 2;</code>
*/
public boolean hasAddr() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
/**
* <code>optional string addr = 2;</code>
*/
public java.lang.String getAddr() {
java.lang.Object ref = addr_;
if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
addr_ = s;
}
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>optional string addr = 2;</code>
*/
public com.google.protobuf.ByteString
getAddrBytes() {
java.lang.Object ref = addr_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
addr_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>optional string addr = 2;</code>
*/
public Builder setAddr(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000002;
addr_ = value;
onChanged();
return this;
}
/**
* <code>optional string addr = 2;</code>
*/
public Builder clearAddr() {
bitField0_ = (bitField0_ & ~0x00000002);
addr_ = getDefaultInstance().getAddr();
onChanged();
return this;
}
/**
* <code>optional string addr = 2;</code>
*/
public Builder setAddrBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000002;
addr_ = value;
onChanged();
return this;
} // @@protoc_insertion_point(builder_scope:proto.ip_address)
} static {
defaultInstance = new ip_address(true);
defaultInstance.initFields();
} // @@protoc_insertion_point(class_scope:proto.ip_address)
} private static final com.google.protobuf.Descriptors.Descriptor
internal_static_proto_ip_address_descriptor;
private static
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_proto_ip_address_fieldAccessorTable; public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\026proto/ip_address.proto\022\005proto\"&\n\nip_ad" +
"dress\022\n\n\002af\030\001 \001(\t\022\014\n\004addr\030\002 \001(\tB!\n\024com.z" +
"iyun.bean.protoB\tIpAddress"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
public com.google.protobuf.ExtensionRegistry assignDescriptors(
com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root;
return null;
}
};
com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
}, assigner);
internal_static_proto_ip_address_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_proto_ip_address_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_proto_ip_address_descriptor,
new java.lang.String[] { "Af", "Addr", });
} // @@protoc_insertion_point(outer_class_scope)
}
  • (3)在Java代码中使用上一步编译好的java类
IpAddress.ip_address.Builder builder = IpAddress.ip_address.newBuilder();
builder.setAddr("10.130.254.6");
builder.setAf("af" + String.valueOf(i));
IpAddress.ip_address ipAddress = builder.build();
publisher.send(ipAddress.toByteArray(), ZMQ.NOBLOCK);

语法

与其他语言类型对比

Google Protocol Buffer入门

package

.proto文件新增一个可选的package声明符,用来防止不同的消息类型有命名冲突。包的声明符会根据使用语言的不同影响生成的代码。对于C++,产生的类会被包装在C++的命名空间中。

枚举(enum)

enum PhoneType //枚举消息类型
{
MOBILE = 0; //proto3版本中,首成员必须为0,成员不应有相同的值
HOME = 1;
WORK = 2;
}

指定字段规则

所指定的消息字段修饰符必须是如下之一:

  • required:一个格式良好的消息一定要含有1个这种字段。表示该值是必须要设置的;
  • optional:消息格式中该字段可以有0个或1个值(不超过1个)。
  • repeated:在一个格式良好的消息中,这种字段可以重复任意多次(包括0次)。重复的值的顺序会被保留。表示该值可以重复,相当于java中的List。

    由于一些历史原因,基本数值类型的repeated的字段并没有被尽可能地高效编码。在新的代码中,用户应该使用特殊选项[packed=true]来保证更高效的编码。如:

    repeated int32 samples = 4 [packed=true];

import

import "myproject/other_protos.proto";

protocol编译器就会在一系列目录中查找需要被导入的文件,这些目录通过protocol编译器的命令行参数-I/–import_path指定。如果不提供参数,编译器就在其调用目录下查找。

protoc命令参数

protoc命令常用法:protoc2.exe -I=./ --java_out=./ ./proto/access_point.proto

protoc参数详解

$ protoc -help
Usage: protoc [OPTION] PROTO_FILES
Parse PROTO_FILES and generate output based on the options given:
-IPATH, --proto_path=PATH Specify the directory in which to search for
imports. May be specified multiple times;
directories will be searched in order. If not
given, the current working directory is used.
--version Show version info and exit.
-h, --help Show this text and exit.
--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.
--decode=MESSAGE_TYPE Read a binary message of the given type from
standard input and write it in text format
to standard output. The message type must
be defined in PROTO_FILES or their imports.
--decode_raw Read an arbitrary protocol message from
standard input and write the raw tag/value
pairs in text format to standard output. No
PROTO_FILES should be given when using this
flag.
-oFILE, Writes a FileDescriptorSet (a protocol buffer,
--descriptor_set_out=FILE defined in descriptor.proto) containing all of
the input files to FILE.
--include_imports When using --descriptor_set_out, also include
all dependencies of the input files in the
set, so that the set is self-contained.
--include_source_info When using --descriptor_set_out, do not strip
SourceCodeInfo from the FileDescriptorProto.
This results in vastly larger descriptors that
include information about the original
location of each decl in the source file as
well as surrounding comments.
--dependency_out=FILE Write a dependency output file in the format
expected by make. This writes the transitive
set of input file paths to FILE
--error_format=FORMAT Set the format in which to print errors.
FORMAT may be 'gcc' (the default) or 'msvs'
(Microsoft Visual Studio format).
--print_free_field_numbers Print the free field numbers of the messages
defined in the given proto files. Groups share
the same field number space with the parent
message. Extension ranges are counted as
occupied fields numbers. --plugin=EXECUTABLE Specifies a plugin executable to use.
Normally, protoc searches the PATH for
plugins, but you may specify additional
executables not in the path using this flag.
Additionally, EXECUTABLE may be of the form
NAME=PATH, in which case the given plugin name
is mapped to the given executable even if
the executable's own name differs.
--cpp_out=OUT_DIR Generate C++ header and source.
--csharp_out=OUT_DIR Generate C# source file.
--java_out=OUT_DIR Generate Java source file.
--javanano_out=OUT_DIR Generate Java Nano source file.
--js_out=OUT_DIR Generate JavaScript source.
--objc_out=OUT_DIR Generate Objective C header and source.
--python_out=OUT_DIR Generate Python source file.
--ruby_out=OUT_DIR Generate Ruby source file.

Protobuf 的不足

Protbuf 与 XML 相比也有不足之处。它功能简单,无法用来表示复杂的概念。

XML 已经成为多种行业标准的编写工具,Protobuf 只是 Google 公司内部使用的工具,在通用性上还差很多。

由于文本并不适合用来描述数据结构,所以 Protobuf 也不适合用来对基于文本的标记文档(如 HTML)建模。另外,由于 XML 具有某种程度上的自解释性,它可以被人直接读取编辑,在这一点上 Protobuf 不行,它以二进制的方式存储,除非你有 .proto 定义,否则你没法直接读出 Protobuf 的任何内容。

参考文献


tips:本文属于自己学习和实践过程的记录,很多图和文字都粘贴自网上文章,没有注明引用请包涵!如有任何问题请留言或邮件通知,我会及时回复。

上一篇:python学习 day2 (3月2日)


下一篇:后端程序员之路 31、Protocol Buffer