簡體   English   中英

如何使用Protocol-buffer在Java中反序列化文件?

[英]How to de-serialize the file in Java by using Protocol-buffer?

想要在C#中創建一個序列化文件,然后想在Java中對其進行反序列化。 為此,我使用協議緩沖庫。 這里想要我做了:

在C#中,我添加了protobuf-net.dll,要序列化的類表示為:

Person.cs

 [ProtoBuf.ProtoContract]
 public class Person
 {
    [ProtoBuf.ProtoMember(1)]
    public int Id {get;set;}
    [ProtoBuf.ProtoMember(2)]
    public string Name { get; set; }
 }

並在main方法中,將其序列化為:

 var person = new Person
    {
        Id = 12345,
        Name = "Fred",
    };
  using (var file = File.Create("somepath\\person.bin"))
    {
        Serializer.Serialize(file, person);
    }

我在ecilpse filesystem- android / sdcard中復制並提取了這個bin文件,並嘗試對其進行反序列化

在eclipse -JAVA中,

添加了protobuf.jar,外部庫和創建的person.proto文件,其中包含:

message Person{
required int32 Id=1;
required string Name=2;
}

任何人都可以建議如何反序列化在C#中創建的對象?

Java文檔對於反序列化由Java版本序列化的對象有何看法? 基本上:“做那個”。 序列化數據沒有區別。

如果問題是Java示例以.proto文件開頭,那么使用:

string proto = Serializer.GetProto<Person>();

雖然你展示的.proto看起來很好。

為C#中創建的文件創建一個InputStream ,然后調用

Person.parseFrom(InputStream)

如果您更願意處理該文件中的字節,則此方法還有其他重載。

如果要實現協議,則需要包含標頭以標識字節所代表的數據類型。 從那里你只需選擇正確的proto來解析數據。

編輯

這是我創建的用於將id映射到類的類,反之亦然,以幫助開發具有protobufs的協議。 如果你沒有開發網絡傳輸協議,這可能沒什么用,但我很確定你是。

我知道你沒有要求這個,但也許你會覺得它很有用。

將id注冊到所有protobuff生成器,然后檢索正確的生成器,以便在接收時反序列化字節。 在發送之前獲取每個protobuf對象的正確ID。 ID將包含在每個數據包中,以便您知道每個數據包中的數據類型。 (數據包在這里是抽象的,這也適用於流協議。)

public class MessageTypeMap {
private final Object lock;
final HashMap<Integer, GeneratedMessageLite> messageParserMap;
final HashMap<Class<?>, Integer> messageClassParserMap;

public MessageTypeMap() {
    this.messageParserMap = new HashMap<Integer, GeneratedMessageLite>();
    this.messageClassParserMap = new HashMap<Class<?>, Integer>();
    this.lock = new Object();
}

public void addMessageType(int typeID, GeneratedMessageLite message) {
    synchronized (this.lock) {
        this.messageParserMap.put(typeID, message);
        this.messageClassParserMap.put(message.getDefaultInstanceForType()
                .getClass(), typeID);
    }
}

public GeneratedMessageLite getBuilderFor(int id) throws ProtocolException {
    synchronized (this.lock) {
        if (this.messageParserMap.containsKey(id)) {
            GeneratedMessageLite lite = this.messageParserMap.get(id);
            return lite;
        } else {
            throw new ProtocolException("No message builder for ID " + id);
        }
    }
}

public int getIDFor(Object obj) throws ProtocolException {
    synchronized (this.lock) {
        if (obj == null) {
            throw new NullPointerException(
                    "Object null while retrieving type id.");
        }
        Class<?> c = obj.getClass();
        if (this.messageClassParserMap.containsKey(c)) {
            int typeID = this.messageClassParserMap.get(c);
            return typeID;
        } else {
            throw new ProtocolException("No type id for class "
                    + c.getSimpleName());
        }
    }
}

}

用法:

MessageTypeMap map = new MessageTypeMap();
//register the person type.
map.addMessageType(100, Person.getDefaultInstance());
//use this to unserialize whatever object some bytes are.
GeneratedMessageLite builder = mpa.getBuilderFor(100);
//be sure to include the type id with each transmission of an object.
int id = map.getIDFor(Person.getDefaultInstance());

Protocol Buffers的常用方法是:

  • 您可以在一個小的.proto文本文件中定義協議。
  • 您在該文件上運行protobuf編譯器
  • proto編譯器生成您需要序列化和解析對象所需的所有語言的源代碼。

您在C#中使用的庫是特殊的。 它不需要.proto文件開頭。 相反,您可以通過注釋類(或C#中的任何術語)在代碼中創建協議。

為了使用Java中的代碼生成協議,您需要.proto文件,因為Java不支持代碼中的那種類型的定義。

您可以手動編寫.proto文件或讓C#庫生成它(請參閱Marc Gravell的回答) - 我建議您生成文件,這樣您就不會在定義中出錯。

獲得該文件后,在.proto文件上運行protobuf編譯器( protoc(dowload) ,它將為您生成.java文件。 該文件具有Person類以及序列化和解析所需的所有內容。

現在,您在項目中包含protobuf[version].jar和生成的.java文件。 項目中不需要.proto文件本身。

完成后,只需使用生成的代碼解析文件:

Person person = Person.parseFrom(new FileInputStream(file));

您編寫的唯一代碼行是上面的代碼。

有關Java集成的更多詳細信息,請參閱官方教程

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM