国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 基于Protobuf動態解析在Java中的應用 包含例子程序

基于Protobuf動態解析在Java中的應用 包含例子程序

2020-12-05 17:05Java教程網 Java教程

下面小編就為大家帶來一篇基于Protobuf動態解析在Java中的應用 包含例子程序。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

最近在做ProtoBuf相關的項目,其中用到了動態解析,網上看了下相關資料和博文都比較少,自己來寫一個記錄一下學習過程。

Protocol Buffers是結構化數據格式標準,提供序列化和反序列方法,用于存儲和交換。語言中立,平臺無關、可擴展。目前官方提供了C++、Java、Python API,也有其他語言的開源api(比如php)。可通過 .proto文件生成對應語言的類代碼
如果已知protobuf內容對應的是哪個類對象,則可以直接使用反序列化方法搞定(Xxx.parseFrom(inputStream)由二進制轉換,TextFormat.merge(string, xxxBuilder)由文本轉換)

而我們經常遇到的情況是,拿到一個被protobuf序列化的二進制內容,但不知道它的類型,無法獲得對應的類對象。這種多見于需要處理各種各樣未知的ProtoBuf對象的系統。ProtoBuf提供了動態解析機制來解決這個問題,它要求提供二進制內容的基礎上,再提供對應類的Descriptor對象,在解析時通過DynamicMessage類的成員方法來獲得對象結果。
最后問題就是Descriptor對象從哪里來?這是通過protoc --descriptor_set_out=$outputpath 命令生成descriptor文件,進而得到的。

代碼如下:

 cinema.proto

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
option java_package="com.liulei.cinema";
 
enum MovieType{
 CHILDREN=1;
 ADULT=2;
 NORMAL=3;
 OHTER=4;
}
 
enum Gender{
 MAN=1;
 WOMAN=2;
 OTHER=3;
}
 
message Movie{
 required string name=1;
 required MovieType type=2;
 optional int32 releaseTimeStamp=3;
 optional string description=4;
}
 
message Customer{
 required string name=1;
 optional Gender gender=2;
 optional int32 birthdayTimeStamp=3;
}
 
message Ticket{
 required int32 id=1;
 required Movie movie=2;
 required Customer customer=3;
}

Main.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public static void main( String[] args ) {
 
  Cinema.Movie.Builder movieBuilder = Cinema.Movie.newBuilder();
  movieBuilder.setName("The Shining");
  movieBuilder.setType(Cinema.MovieType.ADULT);
  movieBuilder.setReleaseTimeStamp(327859200);
 
  System.out.println("Dynamic Message Parse by proto file");
  try {
   byte[] buffer3 = new byte[movieBuilder.build().getSerializedSize()];
   CodedOutputStream codedOutputStream3 = CodedOutputStream.newInstance(buffer3);
   try {
    movieBuilder.build().writeTo(codedOutputStream3);
    System.out.println(buffer3);
   } catch (IOException e) {
    e.printStackTrace();
   }
   String protocCMD = "protoc --descriptor_set_out=cinema.description ./cinema.proto --proto_path=.";
   Process process = Runtime.getRuntime().exec(protocCMD);
   process.waitFor();
   int exitValue = process.exitValue();
   if (exitValue != 0) {
    System.out.println("protoc execute failed");
    return;
   }
   Descriptors.Descriptor pbDescritpor = null;
   DescriptorProtos.FileDescriptorSet descriptorSet = DescriptorProtos.FileDescriptorSet.parseFrom(new FileInputStream("./cinema.description"));
   for (DescriptorProtos.FileDescriptorProto fdp : descriptorSet.getFileList()) {
    Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor.buildFrom(fdp, new Descriptors.FileDescriptor[]{});
    for (Descriptors.Descriptor descriptor : fileDescriptor.getMessageTypes()) {
     if (descriptor.getName().equals("Movie")) {
      System.out.println("Movie descriptor found");
      pbDescritpor = descriptor;
      break;
     }
    }
   }
   if (pbDescritpor == null) {
    System.out.println("No matched descriptor");
    return;
   }
   DynamicMessage.Builder pbBuilder = DynamicMessage.newBuilder(pbDescritpor);
 
   Message pbMessage = pbBuilder.mergeFrom(buffer3).build();
   System.out.println(pbMessage);
 
  } catch (Exception e) {
   System.out.println("Exception");
   e.printStackTrace();
  }
 }

執行結果:

Dynamic Message Parse From byte array
[B@597ccf6e
Movie descriptor found
name: "The Shining"
type: ADULT
releaseTimeStamp: 327859200

 解釋具體過程:

0.首先對.proto文件使用protoc命令,生成的descriptor文件中包含多個類對應的descriptor類信息(序列化的DescriptorSet內容)

1.首先取出序列化的DescriptorSet內容,FileDescriptorSet.parseFrom方法反序列化得到FileDescriptorSet對象

2.取出對應message類型的Descriptor。

 DescriptorSet成員方法getFileList(),拿到多個FileDescriptorProto對象,再構建對應FileDescriptor。
 FileDescriptor的成員方法getMessageTypes()得到所有Message的Descriptor對象,找到對應名字的Descriptor

3.用Descriptor對象反序列化對象

構建DynamicMessage.Builder對象builder,再調用builder的mergeFrom/merge方法得到Message對象

其中Descriptor相關類:

DescriptorProtos.DescriptorSet:protoc編譯出來類文件中包含這個類,描述多個.proto文件中的類

DescriptorProtos.FileDescriptorProto:描述一個完整的.proto文件中的類

DescriptorProtos.FileDescriptor:由DescriptorProtos.FileDescriptorProto構建而來(buildFrom),描述1個完整.proto文件中的所有內容,包括message類型的Descriptor和其他被導入文件的Descriptor。

getMessageTypes()方法:返回List<Descriptors.Descriptor>。得到FileDescriptor內,所有message類型直接兒子的Descriptor列表   

DescriptorProtos.Descriptor:描述一個message類型,通過getName()得到message的類名

以上這篇基于Protobuf動態解析在Java中的應用 包含例子程序就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲色图综合 | 成人午夜视频网 | 在线视频 亚洲 | 国产精品美女久久久免费 | 欧美日韩精品在线观看 | 欧美成人精品在线 | av黄色在线播放 | 综合五月网 | 免费h在线观看 | 亚洲在线视频 | 国产中文一区 | 久久久九九 | 精品国产乱码久久久久久1区2区 | 伊人网在线视频观看 | 最新国产视频 | 久久久精品日本 | 91精品国产91久久久久久 | 色狠狠一区二区三区香蕉 | 91免费影视 | 日韩欧美一级片 | 欧美黑人狂躁日本寡妇 | 最新av在线 | 亚洲国产精品99久久久久久久久 | 欧美第一网站 | 久久精品噜噜噜成人av农村 | 在线91视频 | 中文字幕在线观看一区 | 欧美一区免费 | 国产日韩精品一区二区 | 91亚洲精品一区 | 可以看av的网站 | 久久综合久久久 | 国内在线精品 | 一区二区视频在线观看 | 日韩欧美一区二区三区 | 日本免费中文字幕 | 超碰日韩 | 精品国产一区二区国模嫣然 | 日韩在线免费观看网站 | 欧美一区二区三区在线视频观看 | 1a级毛片免费观看 |