2012-08-17 52 views
1

只是想分享關於protobuf-net的R561版本的觀察。當使用DateTimeOffSet,異常protobuf datetimeoffset

InvalidOperationException異常(否類型定義的串行化器: System.DateTimeOffset)

出現:

我添加的方法與getProto()StreamWriter寫原型文件,現在它可以工作!(原始文件也完全可用)。但是如果我評論這種方法,就會發生同樣的異常。我真的不明白。

希望這個觀察可能有用。


我會盡量做得更清楚。我有一個C#客戶端,其中有一些使用DateTimeOffset參數的對象。我使用protobuf-net(r561)對它們進行了序列化,並添加了一個writeProtoFile()方法來使用getProto()方法編寫proto文件。序列化似乎完美,原始文件也可以。所以,因爲我現在有我的原始文件,所以我可以評論或抑制writeProtoFile()方法:我不需要其他原始文件。所以這裏是我的第一個問題:

- >爲什麼當這個方法(這只是寫一個調用getProto()方法的原始文件)的序列化不起作用了嗎?這是我得到的異常:

沒有爲類型定義的序列化程序:System.DateTimeOffset。

而當我取消註釋writeProtoFile()註釋時,它的工作原理。這裏的方法:

public static void writeProtoFile(String proto) 
{ 
    StreamWriter file = new StreamWriter("c:\\MyprotoFiles\\MyProtoFile.proto"); 
    file.Write(proto); 
    file.Close(); 

} 

我需要這個對象被java客戶端使用。使用proto編譯器生成的java類似乎沒問題,但是當我反序列化它時,出現異常:

com.google.protobuf.InvalidProtocolBufferException:解析協議消息時,輸入意外地在字段中間結束。這可能意味着要麼輸入被截斷,要麼嵌入的消息誤報自己的長度。

我認爲,其原因是產生的DateTimeOffset類(在原,DATETIMEOFFSET包含任何)

message DateTimeOffset { 
} 

類型的DateTimeOffset存在於Java,所以這裏是我的第二個問題: - >有沒有什麼辦法, C#中的dateTimeOffset參數可以被序列化,然後,在反序列化之後,可以在java中使用dateTimeOffset參數?

+0

這個例外很簡單:確實,我沒有加入對此的支持。我不明白你的最後一段 – 2012-08-17 15:09:11

+0

你能否澄清這裏是否有問題?否則,我應該關閉它作爲「不是一個真正的問題」... – 2012-08-17 21:04:11

回答

2

有什麼辦法,在C#中的DATETIMEOFFSET參數可以反序列化後serialialized然後,在Java中的DATETIMEOFFSET參數?

沒有爲任何語言的DateTimeDateTimeOffset沒有定義的基於.proto裝卸,所以沒有有沒有經由protobuf的平臺之間傳輸這樣的數據的方式偶數遠程保證(或任何特定的實現,如protobuf網)。此外,雖然有在2個不同的平臺上稱爲DateTimeOffset,這本身是不夠的,保證他們有相似的語義/範圍/等

對於任何跨平臺的情況下,我會建議只用非常基本的數據,甚至可能只是一個整數(64位)的東西來存儲以毫秒爲單位的1970年代的偏移量。或類似的東西。

爲什麼當這個方法(這只是寫一個調用getProto()方法的原始文件)的序列化不能工作了,是評論或supress?

protobuf網使得零使用任何getProto法或writeProtoFile方法。我會非常謹慎地懷疑,評論/取消評論會改變一些內部行爲,並需要一個具體的重新調查。說實話,這聽起來不太可能。警告:有一種​​方法,但它做了非常不同的事情(並且在V2 API中被GetSchema(Type)取代)。然而

是,完全正確的爲它說:

類型定義沒有串行:System.DateTimeOffset。

由於非常簡單的原因,我沒有定義這種類型的標準串行器。如果你可以定義這個標準的處理,你可以使用SetSurrogate來掛接你選擇的任何電線表示。

回覆:

在解析協議報文,輸入意外現場

以任何方式不應該發生的中間結束。這聽起來像是一個不相關的問題,很可能是數據在傳輸數據時(例如,數據編碼不正確)或覆蓋預先存在的文件而不截斷(最後留下垃圾)。如果你可以說明完全是你如何在平臺之間傳遞二進制文件,我可能會建議更多,但是這裏首先要調查的是:您發送的二進制數據與您收到的二進制數據相同(無所不能)與protobuf的 - 只是一個簡單的:你正確地將我的BLOB是用同樣的長度是每個字節相同)

+0

基本上,我發送一個byteMessage到activeMQ包含序列化的對象。 java客戶端然後使用它。我比較了字節數組,它在C#和java中是相同的。下面是在java中反序列化它的方法(發佈在我的消息的回答中,以使它更精確) – AxelF 2012-08-20 09:45:36

0

這裏是Java的方法反序列化:

public MyObjectProto.MyObject deserialize(byte[] array) { 
    try { 
     CodedInputStream stream = CodedInputStream.newInstance(array); 
     return MyObjectProto.MyObject.parseFrom(stream); 
    } catch (IOException ex) { 
     displayLogs("Error while deserializing the content of message : " + ex); 
     return null; 
    } 
} 

這種反序列化方法會破壞???它?

+0

確定在Java中接收到的字節數組是最初被破壞的。我必須檢查所有的傳輸過程... – AxelF 2012-08-20 12:08:30

+0

它確實歸結爲:你的C#代碼中有一個byte []'......你怎樣才能在你的java中獲得byte []'碼?你把它直接寫到了soecket上嗎?一份文件?你把它轉換成字符串併發送*那個*?如果是的話*如何*?你使用了什麼編碼/解碼過程? – 2012-08-20 14:04:21

0

我用這個方法在C#序列化:

MemoryStream ms = new MemoryStream(); 
Serializer.Serialize<MyObjectType>(ms, myObject); 
byte[] array = ms.ToArray(); 
ms.Close(); 

然後我把它發送到ActiveMQ的主題(發佈 - 訂閱模式) Java的接受它以異步方式,並與以前的方法反序列化(在我的第一個答案)。 我讀了數組,看起來它沒有損壞,但一個是簽名的,另一個不是。在C#中我有10個值高於126。而那些相同的價值觀成爲Java的底片:

byte #58 = 144 in C# , -112 in Java 
byte #67 = 160 in C# , -96 in Java 

,並經過多次試驗,似乎這些值消失時,我不序列化dataTimeOffset參數。