javaprobuf的简单介绍

博主:adminadmin 2022-12-05 17:33:08 75

本篇文章给大家谈谈javaprobuf,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

java怎么使用potobuff

,两个文件:proto.exe, protobuf-Java-2.4.1.jar

2,建立一个工程TestPb,在下面建立一个proto文件件,用来存放【。proto】文件

3,将proto,exe放在工程下,

4,建立一个msg.proto文件:

java 怎么使用protobuf库

1.到 ,选择其中的win版本下载,我选择的是protoc-2.4.1-win32.zip

2.下载一个protobuf-java-2.4.1.jar文件(注意,要与你刚才下的proto.exe版本相同)

然后就开始开发了。

步骤:

1.用记事本编写一个.proto文件:

}如:编写的是test.proto

package protobuf;

option java_package = "com.sq.protobuf";

option java_outer_classname = "FirstProtobuf";

message testBuf {

required int32 ID = 1;

required string Url = 2;

}

将其放在与刚解压的protoc.exe同级目录中。

2.在cmd中,到protoc-2.4.1-win32文件夹下,

执行

E:\protoc-2.4.1-win32 protoc.exe --java_out=./ test.proto

则可以找到的一个生成的FirstProtobuf.java文件。

3.在MyEclipse中新建一个java project,建立包com.sq.protobuf,然后将刚才生成的FirstProtobuf.java文件放在其下面。

此时会报错,因为没有引入jar包,在package视图下,将protobuf-java-2.4.1.jar引入,即可解决问题。

4.建立测试文件:

package com.sq.protobuf.test;

import java.io.ByteArrayInputStream;

import java.io.InputStream;

import java.sql.Blob;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.Statement;

import com.google.protobuf.InvalidProtocolBufferException;

import com.sq.protobuf.FirstProtobuf;

public class Test {

public static void main(String[] args) {

//序列化过程

//FirstProtobuf是生成类的名字,即proto文件中的java_outer_classname

//testBuf是里面某个序列的名字,即proto文件中的message testBuf

FirstProtobuf.testBuf.Builder builder=FirstProtobuf.testBuf.newBuilder();

builder.setID(777);

builder.setUrl("shiqi");

//testBuf

FirstProtobuf.testBuf info=builder.build();

byte[] result = info.toByteArray() ;

String driver = "oracle.jdbc.driver.OracleDriver";

String url = "jdbc:oracle:thin:@10.64.59.12:1521/orcl";

String user = "parkingsystem";

String password = "parkingsystem";

try {

Class.forName(driver);

Connection conn = DriverManager.getConnection(url, user, password);

if(!conn.isClosed()){

System.out.println("Succeeded connecting to the Database!");

//此处只能使用prepareStatement

PreparedStatement ps = conn.prepareStatement("insert into test(id,test) values (1,?)");

//写入数据库,要把它改写为流的形式

ByteArrayInputStream stream = new ByteArrayInputStream(result);

ps.setBinaryStream(1,stream,stream.available());

Statement statement = conn.createStatement();

Blob blob = null;

ps.execute();

////////////////上述完成将写入数据库的操作,数据库中对应的字段的属性要设置为Blob

String sql = "select test from test";

ResultSet rs = statement.executeQuery(sql);

if(rs.next()){

blob = rs.getBlob("test");

}

byte[] s = blob.getBytes(1,(int)blob.length());

FirstProtobuf.testBuf testBuf = FirstProtobuf.testBuf.parseFrom(s);

System.out.println(testBuf);

conn.close();

}

}catch(Exception e) {

e.printStackTrace();

}

//反序列化过程

try {

FirstProtobuf.testBuf testBuf = FirstProtobuf.testBuf.parseFrom(result);

System.out.println(testBuf);

} catch (InvalidProtocolBufferException e) {

e.printStackTrace();

}

}

}

发现可以将其序列化,插入到数据库,并可以从数据库出取出后,反序列化,内容可以正常显示出来。

注意的就是2点:

1.不能用statement,否则无法插入blob类型的数据

2.为参数赋值时,要用

ByteArrayInputStream stream = new ByteArrayInputStream(result);

ps.setBinaryStream(1,stream,stream.available());

protobuffer java中文乱码怎么解决

protobuf支持非UTF8字符串

protobuf规范string类型是必须是UTF8字符,但在C/C++中可以直接调用set方法设置任意编码方式的字符串,也可以直接取得对应字符串,但在控制台中会打印出编码不是UTF8字符的错误信息.

查看protobuf源代码发现是在wire_format.h中有一函数VerifyUTF8String()里进行编码判断的,而且有一宏定义GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED可以取消此错误信息.估计google当初开发时用的是std::string类型,并没有编码方面的强制要求,只是在跨平台时没有统一编码容易引起问题,才统一使用UTF8方式传送字符串.

但像Java,Python缺省就是支持UNICODE,在protobuf库中就已经做了转换或检测,可以修改相关代码不做此转换或检测.

如python中修改lib中的protobufxxx.egg中的decoder.py的StringDecoder()方法,将value.append(local_unicode(buffer[pos:new_pos], 'utf-8'))

改为value.append(buffer[pos:new_pos])

,将field_dict[key] = local_unicode(buffer[pos:new_pos], 'utf-8')

改为field_dict[key] = buffer[pos:new_pos]

即可,Python即不会报异常错误,也能正确取得任意编码的字符串,但需要注意取出后需要进行编码(decode("gbk"))才能正确显示.

另外type_checkers.py中CheckValue()中对str的判断也需要去掉,encoder.py中带'utf-8'的全改了,才能正常编码.

至于如此改会不会有其它潜在的问题,还有待测试.

如何提供java编译protobuf协议文件的速度

ProtoBuf java 包编译

ProtoBuf的官方下载包并不包含jar文件,需要用户自己configure/make….来自行编译。由于Windows上没有编译环境,就用了一个笨一点方法处理了。

分别下载:

protobuf-2.4.1.zip ProtoBuf的源文件(包含了C++/Java/Python)的源文件

protoc-2.4.1-win32.zip 已经编译过的用于Windows平台的protoc命令(该命令用于将.proto文件转化为Java或C++源文件)。

分别解析这两个文件,你可以在protoc-2.4.1-win32.zip解压后的文件中找到一个protoc.exe文件,将其copy到protobuf-2.4.1/src目录下,然后进入protobuf-2.4.1/java,执行:

mvn install

如果没有安装maven的话,可以在网上找一下maven的安装手册。

编译完成后可以在protobuf-2.4.1/java/target目录中找到protobuf-2.4.1.jar文件.

后记

protobuf-2.4.1.zip里面同时包含了protoc和java等的源文件,如果按照官方教程来安装的话,就是先产生出protoc编译器,然后再生成jar包。由于mvn install同时包含了编译和测试过程,而测试代码又依赖于protoc编译器,所以就需要单独下载protoc编译器,并置于src目录下了。

如果不需要验证编译结果(不执行单元测试),则可以如下:

下载protobuf-2.4.1.zip并解压,进入到protobuf-2.4.1/java

mvn install –Dmaven.test.skip=true

这样就可以了。

Protobuf语法介绍

我们先看看官方文档给出的定义和描述

简单来讲, ProtoBuf 是结构数据序列化方法,可简单类比于,其具有以下特点:

在protobuf中,协议是由一系列的消息组成的。因此最重要的就是定义通信时使用到的消息格式。一个Protobuf 消息(对应JAVA类),由至少一个字段(对应Java类属性)组合而成。

消息的定义很简单,就是message关键字加上消息的名字

字段定义格式:

限定修饰符 | 数据类型 | 字段名称 | = | 字段编码

required:

表示是一个必须字段,必须相对于发送方,在发送消息之前必须设置该字段的值,对于接收方,必须能够识别该字段的意思。发送之前没有设置required字段或者无法识别required字段都会引发编解码异常,导致消息被丢弃。

optional:

表示是一个可选字段,可选对于发送方,在发送消息时,可以有选择性的设置或者不设置该字段的值。对于接收方,如果能够识别可选字段就进行相应的处理,如果无法识别,则忽略该字段,消息中的其它字段正常处理。---因为optional字段的特性,很多接口在升级版本中都把后来添加的字段都统一的设置为optional字段,这样老的版本无需升级程序也可以正常的与新的软件进行通信,只不过新的字段无法识别而已,因为并不是每个节点都需要新的功能,因此可以做到按需升级和平滑过渡。

repeated:

表示该字段可以包含0~N个元素。其特性和optional一样,但是每一次可以包含多个值。可以看作是在传递一个数组的值。类比于Java这边的List

protobuf定义了一套基本的数据类型,几乎都映射了Java语言的基础数据类型(主要以Java为例)

详见下面表格

字段的命名方式与Java的命名方式大致一致

字段编码是一个序列化和反序列化的标记值,有了该值,通信双方才能互相识别对方的字段。当然相同的编码值,其限定修饰符和数据类型必须相同。编码值的取值范围为 1~2^32(4294967296)

其中 1~15的编码时间和空间效率都是最高的,编码值越大,其编码的时间和空间效率就越低(相对于1-15),当然一般情况下相邻的2个值编码效率的是相同的,除非2个值恰好实在4字节,12字节,20字节等的临界区。比如15和16

1900~2000编码值为Google protobuf 系统内部保留值,建议不要在自己的项目中使用。protobuf 还建议把经常要传递的值把其字段编码设置为1-15之间的值

完整的消息定义示例

枚举的定义和Java 相同,使用 enum 关键字,但是有一些限制。

枚举值必须大于等于0的整数。

使用分号 ; 分隔枚举变量而不是Java 语言中的逗号 ,

示例:

你可以将其他消息类型用作字段类型。已我们现在IM的为例,在每一个CSSendLiveRoomMsgReq消息中包含ImMsgBody消息,此时可以在相同的.proto文件中定义一个ImMsgBody消息类型,然后在CSSendLiveRoomMsgReq消息中指定一个ImMsgBody类型的字段

示例:

如果你的消息中有很多可选字段, 并且同时至多一个字段会被设置, 你可以加强这个行为,使用oneof特性节省内存,Oneof字段就像可选字段, 除了它们会共享内存, 至多一个字段会被设置。 设置其中一个字段会清除其它字段。

为了在.proto定义Oneof字段, 你需要在名字前面加上oneof关键字, 比如下面例子的ImMsgBody:

oneof的特性

javaprobuf的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于、javaprobuf的信息别忘了在本站进行查找喔。

The End

发布于:2022-12-05,除非注明,否则均为首码项目网原创文章,转载请注明出处。