1. ホーム
  2. c#

Protobuf-netを使用すると、突然、不明なワイヤタイプに関する例外が発生しました。

2023-09-24 01:07:17

質問

(これは私がRSSで見た質問の再投稿ですが、OPによって削除されました。私はこの質問が別の場所で何度も尋ねられるのを見たので、それを再追加しました; Wiki for "good form")

突然ですが、私のところに ProtoException をデシリアライズすると、メッセージは次のようになります:不明なワイヤタイプ 6

  • wire-typeとは何ですか?
  • ワイヤータイプの値の違いとその説明について教えてください。
  • あるフィールドが問題を引き起こしていると思われますが、これをデバッグするにはどうしたらよいでしょうか。

どのように解決するのですか?

まず最初に確認すること。

は入力データがprotobufデータであるか?他の形式 (json、xml、csv、binary-formatter) や、単に壊れたデータ ("internal server error" html placeholder text page など) をパースしようとした場合、次のようになります。 は動作しません。 .


ワイヤー型とは何ですか?

これは3ビットのフラグで、次のデータがどのようなものかを(大まかに言えば、結局は3ビットしかないのですが)伝えるものです。

プロトコルバッファの各フィールドには、どのフィールド (番号) を表しているかを示すヘッダーが前に付いています。 この「どのようなデータか」というのは、次のようなケースをサポートするために不可欠です。 予期しない のデータがストリームにある場合 (たとえば、一方の端のデータ型にフィールドを追加した場合) をサポートするために不可欠です。 これはシリアライザーにそのデータを過去に読み込む方法 (または必要であればラウンドトリップ用に保存する方法) を知らせるものです。

異なるワイヤタイプの値とその説明は何ですか?

  • 0: 変長整数 (最大 64 ビット) - MSB が継続を示す base-128 エンコード (enum を含む整数型のデフォルトとして使用されます)
  • 1: 64ビット - 8バイトのデータ( double または 選択的に に対して long / ulong )
  • 2: length-prefixed - 最初にvariant-lengthエンコーディングで整数を読み、何バイトのデータが続くかを示します(文字列に使用されます。 byte[] 配列、および子オブジェクトのプロパティ / リストのデフォルトとして使用されます)
  • 3: "start group" - 開始/終了タグを使用する子オブジェクトをエンコードするための代替メカニズム - Google ではほとんど非推奨となっており、予期しないオブジェクトを通過して "seek" できないため、子オブジェクト フィールド全体をスキップする方が高くつきます。
  • 4: "end group" - 3 と双璧をなすものです。
  • 5: 32ビット - 4バイトのデータ( float または 選択的に に対して int / uint およびその他の小さな整数型)

フィールドが原因だと思われますが、どのようにデバッグすればよいのでしょうか?

ファイルへのシリアライズを行っていますか?その 最も可能性が高い の原因は、既存のファイルを上書きしてしまったが、切り捨てていないことです。 でした。 200 バイトであったものを 182 バイトで書き直した場合です。現在、ストリームの末尾に 18 バイトのゴミがあり、これが障害になっています。プロトコルバッファを書き直すときは、ファイルを切り詰めなければなりません。これを行うには FileMode :

using(var file = new FileStream(path, FileMode.Truncate)) {
    // write
}

または、代わりに SetLength を書き込む。

file.SetLength(file.Position);

その他考えられる原因

ストリームをシリアル化されたものと異なる型に(誤って)デシリアライズしている。これが起きていないことを確認するために、会話の両側をダブルチェックする価値があります。