[英]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
文本文件中定義協議。 您在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.