2

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; }
 }

メインメソッドでは、次のようにシリアル化します。

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

このbinファイルをコピーしてecilpseファイルシステム-android / sdcardに取り込み、デシリアライズしようとしました

日食 -JAVA では、

protobuf.jar、外部ライブラリを追加し、以下を含む person.proto ファイルを作成しました。

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

C# で作成されたオブジェクトを逆シリアル化する方法を提案してもらえますか?

4

3 に答える 3

3

InputStreamC# で作成したファイルに を作成し、呼び出します

Person.parseFrom(InputStream)

そのファイルのバイトを処理したい場合は、このメソッドに他のオーバーロードがあります。

プロトコルを実装している場合は、バイトが表すデータの種類を識別するためにヘッダーを含める必要があります。そこから、データを解析する正しい proto を選択するだけです。

編集

これは、protobufs を使用したプロトコルの開発を支援するために、ID をクラスに、またはその逆にマッピングするために作成したクラスです。ネットワーク伝送用のプロトコルを開発していない場合、これは役に立たないかもしれませんが、そうであると確信しています。

あなたがこれを求めていないことは知っていますが、おそらく役に立つでしょう。

すべてのプロトバフ ジェネレーターに ID を登録し、受信時にバイトをシリアル化解除するための正しいジェネレーターを取得します。送信する前に、各 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());
于 2013-08-05T17:31:21.573 に答える
2

Protocol Buffers の通常の動作方法は次のとおりです。

  • 小さな.protoテキスト ファイルでプロトコルを定義します。
  • そのファイルに対して protobuf コンパイラを実行します
  • proto コンパイラは、オブジェクトのシリアル化と解析に必要なすべての言語でソース コードを生成します。

C# で使用するライブラリは特殊です。.proto最初にそのファイルは必要ありません。代わりに、クラスに注釈を付けることによって (または C# の用語が何であれ)、コード内でプロトコルを作成できます。

.protoJava からコード内で生成されたプロトコルを使用するには、Java がコード内でそのタイプの定義をサポートしていないため、ファイルが必要です。

ファイルを手動で作成するか.proto、C# ライブラリに生成させることができます (Marc Gravell の回答を参照)。定義を間違えないようにファイルを生成することをお勧めします。

そのファイルを取得したら、そのファイルに対して protobuf コンパイラ ( protoc) (ダウンロード)を実行すると、ファイル.protoが生成さ.javaれます。そのファイルには、Personシリアル化と解析に必要なクラスとすべてが含まれています。

ここprotobuf[version].jarで、 と生成された.javaファイルの両方をプロジェクトに含めます。.protoファイル自体はプロジェクトでは必要ありません。

それが完了したら、生成されたコードを使用してファイルを解析するだけです。

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

あなたが書く唯一のコード行は、上記のものです。

Java 統合の詳細については、公式チュートリアルを参照してください。

于 2013-08-05T19:46:08.243 に答える