c++ java通信 protocol buffer,google protocol buffer (C++,Java序列化应用实例)

google protocol buffer (C++,Java序列化使用实例)

转载,请注明出处: http://blog.csdn.net/eclipser1987/article/details/8525383  (eclipser@163.com)

1.下载安装:

google protocol buffer 的官网地址是:http://code.google.com/p/protobuf/

建议下载稳定版本:protobuf-2.4.1  linux下载protobuf-2.4.1.tar.bz2   windows下载protobuf-2.4.1.zip

这里以linux下安装为实例:

tar -xvf protobuf-2.4.1.tar.bz2

cd protobuf-2.4.1

./configure --prefix=/usr/local/protobuf-2.4.1

make

make install

2.使用protobuf

查看编译生成的目录

cd /usr/local/protobuf-2.4.1

ls

bin  include  lib

其中,bin中的protoc是.proto文件的处理器,可用这个工具生成cpp,java,python文件.

由于系统常用这个工具,可以将其ln或者直接拷贝到系统环境bin下

ln -s /usr/local/protobuf-2.4.1/bin/protoc /usr/bin/protoc

同样,可以将头文件ln或者直接拷贝到系统环境

ln -s /usr/local/protobuf-2.4.1/include/google /usr/include/google

将lib文件ln或者直接拷贝到系统环境

略,方法同上.

这个时候,protobuf的开发环境已经搭建了.

3.如何使用protobuf

数据结构体:

message message_name{message_body;}

message_body格式:

例如required int32 query = 1[defaut=10];

形式为:rule type name = value[other_rule];

规则:

required表示必须具有该值域;

optional表示可选的值域;

repeated表示可重复的值域(即>=0);

其中requered/optional是常用rule,而repeated则不常用同时因为是历史遗留现使用repeated int32 samples=4[packed=true];形式;

value值:

value值最小为1,是底层编码时使用其中1-15占一位,>15则会占多位;

不同的message中的value值互不干扰,常以1开始计数。

数据类型之基本类型:

.proto Type C++ Type Java Type

double double double

float float float

int32 int32 int

int64 int64 long

uint32 uint32 int

uint64 uint64 long

sint32 int32 int

sint64 int64 long

fixed32 uint32 int

fixed64 uint64 long

sfixed32 int32 int

sfixed64 int64 long

bool bool boolean

string string String

bytes string ByteString

数据类型之复杂类型:

复杂类型主要包括:枚举,其他message,groups等。

枚举定义例如:enum Corpus{WEB=0;LOCAL=1}

枚举定义在message中。

可以使用其他message作为类型来定义成员。

groups我的理解有些像C++中的union结构。

嵌套定义:

可以嵌套定义message结构,而嵌套定义的message被其他message作为成员类型时需要形式为outmessage.inmessage形式。

包结构:

定义形式:package foo.bar;

对应C++中则生成两个命名空间foo和bar,且bar定义在foo中;

可以通过import "myproject/other_protos.proto";来引入.proto文件;

引用其他package中message时需要完整的package路径;

Services:

主要用于RPC系统中,在.proto中定义接口;

定义形式如例子:

service SearchService {

rpc Search(SearchRequest) return (SearchResponse);

}

.proto文件编译:

格式:

protoc -–proto_path=(.proto文件路径) -–cpp_out=(.cc .java生成文件路径) (.proto文件路径)/?.proto

-–proto_path 简化为: --I

其中可根据需要更改:cpp_out选项为java_out/python_out。

例子:

protoc -I=./ --cpp_out=./ model.proto

我们拿个例子:

建立model.proto

package cn.vicky.model.seri;

message User {

required int32 id = 1; // 主键,唯一

required string username = 2; // 帐号

required string password = 3; // 密码

optional string email = 4; // 邮箱(可选)

repeated Person person = 5; // 账户拥有的角色(可以重复)

}

message Person {

required int32 id = 1; // 主键,唯一

required string name = 2; // 角色名字

repeated PhoneNumber phone = 3; // 电话号码(可以重复)

}

// 枚举类型

enum PhoneType {

MOBILE = 0;

HOME = 1;

WORK = 2;

}

message PhoneNumber {

required string number = 1;

optional PhoneType type = 2 [default = HOME];

}

protoc -I=./ --cpp_out=./ model.proto

将生成对应的model.pb.h  model.pb.cc

使用:

编写main.cpp

/*

* File: main.cpp

* Author: Vicky.H

* Email: eclipser@163.com

*/

#include

#include

#include "model.pb.h"

/*

*

*/

int main(void) {

// 创建User对象

cn::vicky::model::seri::User u;

u.set_id(1);

u.set_username("Jack");

u.set_password("123456");

u.set_email("289997171@qq.com");

// 创建User中的一个角色

cn::vicky::model::seri::Person* _person1 = u.add_person();

_person1->set_id(1);

_person1->set_name("P1");

// 创建角色中的一个电话号码:1

cn::vicky::model::seri::PhoneNumber* _phone1 = _person1->add_phone();

_phone1->set_number("+8613618074943");

_phone1->set_type(cn::vicky::model::seri::MOBILE);

// 创建角色中的一个电话号码:2

cn::vicky::model::seri::PhoneNumber* _phone2 = _person1->add_phone();

_phone2->set_number("02882334717");

_phone2->set_type(cn::vicky::model::seri::WORK);

// 创建User中的一个角色

cn::vicky::model::seri::Person* _person2 = u.add_person();

_person2->set_id(2);

_person2->set_name("P2");

// 创建角色中的一个电话号码:1

cn::vicky::model::seri::PhoneNumber* _phone3 = _person2->add_phone();

_phone3->set_number("+8613996398667");

_phone3->set_type(cn::vicky::model::seri::MOBILE);

// 创建角色中的一个电话号码:2

cn::vicky::model::seri::PhoneNumber* _phone4 = _person2->add_phone();

_phone4->set_number("02882334717");

_phone4->set_type(cn::vicky::model::seri::WORK);

// 持久化:

// std::fstream out("User.pb", std::ios::out | std::ios::binary | std::ios::trunc);

// u.SerializeToOstream(&out);

// out.close();

// 对象化:

cn::vicky::model::seri::User u2;

std::fstream in("User.pb", std::ios::in | std::ios::binary);

if (!u2.ParseFromIstream(&in)) {

std::cerr << "Failed to parse User.pb." << std::endl;

exit(1);

}

std::cout << u2.id() << std::endl;

std::cout << u2.username() << std::endl;

std::cout << u2.password() << std::endl;

std::cout << u2.email() << std::endl;

std::cout << "---------------------------" << std::endl;

for(int i = 0;i < u2.person_size();i++) {

cn::vicky::model::seri::Person* p = u2.mutable_person(i);

std::cout << p->id() << std::endl;

std::cout << p->name() << std::endl;

for (int j = 0;j < p->phone_size();j++) {

cn::vicky::model::seri::PhoneNumber* phone = p->mutable_phone(j);

std::cout << phone->number() << std::endl;

}

std::cout << "---------------------------" << std::endl;

}

return 0;

}

需要 -lpthread -lprotobuf          (protobuf已经被加载到了/usr/lib)

执行后,会生成:User.pb,存储的二进制文件.可以直接打开看看.

以上,我们使用了protobuf完成c++下的对象序列化以及反序列化.这里我们要描述一下protobuf的优势了.

那就是protobuf性能高效,他的序列化速度比java自身的序列化还快数倍,而且支持3种语言对象的转换.以往,在C++中序列化的对象,比如用boost serialization持久化的对象,无法用java展开,即便使用jni技术,这也是非常麻烦的事.现在我们有protobuf了.

运行: protoc -I=./ --java_out=./ model.proto 将生成对应的Java类

我们可以用Maven建立一个Java工程.需要protobuf的java依赖库:

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

cn.vicky

google_protobuf_01_java

1.0-SNAPSHOT

jar

google_protobuf_01_java

http://maven.apache.org

UTF-8

com.google.protobuf

protobuf-java

2.4.1

编写Test.java

package cn.vicky.model.seri;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.InputStream;

/**

*

* @author Vicky.H

*/

public class Test {

public static void main(String args[]) throws FileNotFoundException, IOException {

File file = new File("User.pb");

InputStream is = new FileInputStream(file);

Model.User user = Model.User.parseFrom(is);

System.out.println(user.getId());

System.out.println(user.getUsername());

System.out.println(user.getPassword());

System.out.println(user.getEmail());

System.out.println("-------------------");

for (Model.Person person : user.getPersonList()) {

System.out.println(person.getId());

System.out.println(person.getName());

for (Model.PhoneNumber phone : person.getPhoneList()) {

System.out.println(phone.getNumber());

}

System.out.println("-------------------");

}

is.close();

}

}

运行:

1

Jack

123456

289997171@qq.com

---------------------------

1

P1

+8613618074943

02882334717

---------------------------

2

P2

+8613996398667

02882334717

---------------------------

运行 SUCCESSFUL (总时间:  594ms)

OK.以上我们完成了probuf在C++,Java的使用.非常强力是不是!!

设计思想:

在POJO中,protobuf生成的类,处于PO状态,而且这个生成的类,我们最好不要做任何修改或太大的修改,那么,这个时候,我们可以通过C++友元类的方式,为PO添加一个JO类.将数据结构算法分离,也就是说,PO是数据,JO放算法!!!

与数据库的结合:

mysql oracle 可以很轻松的存储,读取二进制.还有一点,那就是通过这种方式,我们可以非常简单的将C++的对象,持久化的redis之类内存数据库了.

附:

model.proto也可以这样定义,不过,本人认为,上面的更好,这里仅供参考,采用什么样的方式,生成的类的结构也不太一样.

package cn.vicky.model.seri;

message User {

required int32 id = 1; // 主键,唯一

required string username = 2; // 帐号

required string password = 3; // 密码

optional string email = 4; // 邮箱(可选)

message Person {

required int32 id = 1; // 主键,唯一

required string name = 2; // 角色名字

// 枚举类型

enum PhoneType {

MOBILE = 0;

HOME = 1;

WORK = 2;

}

message PhoneNumber {

required string number = 1;

optional PhoneType type = 2 [default = HOME];

}

repeated PhoneNumber phone = 3; // 电话号码(可以重复)

}

repeated Person person = 5; // 账户拥有的角色(可以重复)

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/267736.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hadoop等的下载地址

有的时候要使用老的版本hadoop,找不到地方下载,保存连接如下http://archive.apache.org/dist/hadoop/core/http://archive.cloudera.com/cdh/3/

前端“黑话”polyfill

前言 在Web前端开发这个日新月异的时代&#xff0c;总是需要阅读一些最新的英文技术博客来跟上技术的发展的潮流。而有时候会遇到一些比较高频的“黑话”&#xff0c;在社区里面可能已经是人人皆知的“共同语言”&#xff0c;而你接触的少就偏偏看不懂。就像现在几乎所有中国人…

java 什么是线程同步,java多线程同步集合是什么?并发集合是什么?

java中关于集合的内容也是十分丰富的&#xff0c;而且相关的知识点也是十分多的。多线程集合所涵盖的范围是十分广阔的。今天就来为大家介绍一下&#xff0c;java多线程同步集合是什么以及并发集合是什么?一起来看看吧。首先我们需要知道的是&#xff0c;无论是同步集合还是并…

windwos 批处理重定向, 讲的策彻底

本帖主要参考了《命令行参考》和一些前辈的文献&#xff0c;并加入了我自己的一些理解&#xff0c;希望能对各位有所帮助。 《命令行参考》中对重定向操作符有所论述&#xff0c;不过实在晦涩难懂&#xff0c;并且还有些错误&#xff0c;不利于大家理解。重定向的简单用法相信大…

matlab里符号的写法,Matlab中特殊符号的写法

Matlab的figure中输入上标、下标、特殊符号或字体坐标轴标注&#xff1a;1. 控制坐标轴尺度长度&#xff1a;set(gca,XLim,[-pi/2 pi])2. 定制自己想标注的刻度&#xff1a;(1)set(gca,XTick,[-pi/2:pi/4:pi])(2)set(gca,XTickLabel,{-pi/2 -pi/4: 0 pi/4 pi/2 pi*3/4 pi})3. 反…

VB.NET怎样开发自定义Windows控件

前言 Microsoft&reg; Visual Basic&reg; 的组件支持历来都是它的一大卖点&#xff0c;于是第三方软件开发商们纷纷开发出各种具有新功能性的可视控件 (也有少数非可视控件) 供 Visual Basic 程序员选用。这种特殊的 Visual Basic 开发形式创造了无数的第三方控件——有…

内核配置

make config&#xff1a;基于文本模式的交互式配置。 make menuconfig&#xff1a;基于文本模式的菜单型配置。&#xff08;推荐使用&#xff0c;空格键选择&#xff1a;*&#xff1a;y&#xff0c;M:M,空格&#xff1a;N&#xff09; make oldconfig&#xff1a;使用已有的配置…

mysql数据库面试总结(一)

1、数据库优化  1&#xff09;数据库范式 第一范式&#xff08;1NF&#xff09;&#xff1a;强调的是列的原子性&#xff0c;即列不能够再分成其他几列。 如电话列可进行拆分---家庭电话、公司电话 第二范式&#xff08;2NF&#xff09;&#xff1a;首先是 1NF&#xff0c;另外…

思科路由器IKEV2 L2L***预共享密码认证最简化配置

一.概述:思科路由器对于IKEV2&#xff0c;是有很多预配的&#xff0c;因此可以很少的配置就能完成IKEV2的配置。二.基本思路&#xff1a;A.两边都用SVTI的方式配置Flex ***B.没有用动态路由&#xff0c;配置静态路由,如果一边用DVTI&#xff0c;则需要两边配置静态路由三.测试拓…

Oracle存储过程学习

存储过程创建语法&#xff1a; create or replace procedure 存储过程名&#xff08;param1 in type&#xff0c;param2 out type&#xff09; as 变量1 类型&#xff08;值范围&#xff09;; 变量2 类型&#xff08;值范围&#xff09;; Begin Select count(*) into 变量1 fro…

关于通过Sql注入直接拖数据的讨论

和谐社会&#xff0c;拒绝***。 最近在老外的Blog上逛&#xff0c;突然发现我一直以来Dump数据的态度终于得到了某些老外的认可&#xff0c;通过Sql注入点直接拖下数据库是可行的。而且很多老外已经开始开发这方面的直接Dump数据的工具&#xff0c;并讨论相关的算法。很多人说行…

php mysql_query返回,php的mysql_query()函数处理以下( )指令成功就可以返回查询后的结果集。...

【多选题】皮亚杰认为影响发展的因素有( )。【单选题】关于宽带薪酬设计说法错误的是( )【判断题】《省煤炭厅2000年度工作总结》是一个文章式总结的标题。( )【单选题】小儿惊厥最常见的原因是:【单选题】The shipping company makes a notation such as “5 cartons have bee…

php-fpm配置笔记

Posted on 2013 年 2 月 27 日 3,070 Views 不得不说,英文不好弄linux服务器有时是挺痛苦的,苦逼的博主没好好学习英文,导致被lnmp折腾的够呛. php-fpm配置不当&#xff0c;导致服务器经常出现502错误&#xff0c;上个学期多次调整都没有解决&#xff0c;网上找来资料&#xff…

php xcat createadmin,php xcat update升级后出错,不知怎么弄

恢复再次升级&#xff0c;同样的错误&#xff0c;没法升级了吗Fetching originremote: Enumerating objects: 353, done.remote: Counting objects: 100% (353/353), done.remote: Compressing objects: 100% (3/3), done.remote: Total 802 (delta 350), reused 350 (delta 35…

JNDI(datasource)在tomcat,JBOSS下的spring+quartz配置

由于项目中多个小应用&#xff08;类似插件&#xff09;需要使用数据库连接池&#xff0c;不能为每一个应用中配置连接池。故采用JNDI的模式进行配置。 我们使用的web服务器有tomcat和jboss两种。分别介绍其在这两种服务器下并且在两种应用模式springhebernat与quartz下的配置。…

UVA10561 Treblecross

Treblecross 题目大意&#xff1a;给定一个带有.和X的字符串作为初始局面&#xff0c;两人轮流游戏&#xff0c;将.修改为X&#xff0c;当一个人放下X后&#xff0c;出现三个连续的X&#xff0c;游戏接触&#xff0c;放下X的人获胜。判断先手必胜还是必败&#xff0c;并给出第一…

解决VS2005 远程工具无法通过同步软件连接S5pv210 样机的问题

居然无法连接&#xff0c;记得以前遇到过的 1 分钟前 上传下载附件 (58.21 KB)后来还是看MSDN解决了MSDN连接如下http://msdn.microsoft.com/en-us/library/ee480836.aspx——Troubleshooting a Connection to a Target Device That Uses Platform Manager 转载一下sunrain_hjb…

matlab画曲面二次,如何用matlab绘制二次B样条三维曲面(已知控制点和节点矢量)?...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼小弟初来乍到&#xff0c;现在需要用matlaB绘制二次B样条曲面&#xff0c;现在已知信息&#xff1a;小弟做这个已经一个星期了&#xff0c;现在无任何进展&#xff0c;现在是万分着急&#xff0c;希望高手们给小弟指点一二&#xf…

一些应该记住的东西(持续更新?再也不会更新了)

没什么用的目录 1.积性函数与杜教筛 2.搜索的几种优化与考试期望得分 3.乱讲 4.模拟退火系列 5.生成函数系列 2018.1.18 首先写写数学方面的吧(因为现在在学)……毕竟这里面的公式浩如烟海…… 对着表推了十分钟愣是没发现……明明上午还证明过…… 还有就是通过算贡献化简一些…

传说中的window8 的种子

2019独角兽企业重金招聘Python工程师标准>>> 趁着更新服务器最后时刻 发个种子 有兴趣的可以去看看 http://dl.dbank.com/c03a8fck07 转载于:https://my.oschina.net/qutterrtl/blog/28368