4


0

C#シリアル化を使用して、カスタム形式のバイナリファイルを読み取ることはできますか?

C#プログラムに読み込むカスタムバイナリファイルがあります。

MSBファースト、LSBファースト、変数の順序が異なるいくつかの異なるフォーマットがあります。

現在、適切なバイト数を一度に1つずつ読み取るクラスがあります。

非常に遅いので、できる限りパフォーマンスを改善したいと考えています。

シリアル化のパフォーマンスは向上する可能性がありますか? もしそうなら、これは私が記述したシナリオで可能ですか? BinaryFormatterをビッグ/リトルエンディアン形式にカスタマイズすることは可能ですか?

ありがとう。

2 Answer


2


`BinaryFormatter`でそれを行うことはできません-オブジェクトの周りに追加のメタデータ/パディングを期待します。 「ストリーム」から、またはバイナリリーダーを介して同様に手動で読み取る必要があります。

いくつかの非常に類似したコードを実行したら、ストリームの上部にある独自のリーダーを作成します。次のようなメソッドを使用します。 >> `)バイトを組み立てます。 ただし、_importantly_バッキングバッファーを使用して、基になるストリームへの呼び出しの量を減らします(バッファーを使用しても、許容できないほど遅くなる可能性があります)。

これを行うprotobuf-netのコードを紹介します…​ 特にhttp://code.google.com/p/protobuf-net/source/browse/trunk/protobuf-net/ProtoReader.cs [ProtoReader]を例に挙げます。

    ///
    /// Reads an unsigned 32-bit integer from the stream; supported wire-types: Variant, Fixed32, Fixed64
    ///
    public uint ReadUInt32()
    {
        switch (wireType)
        {
            case WireType.Variant:
                return ReadUInt32Variant(false);
            case WireType.Fixed32:
                if (available < 4) Ensure(4, true);
                position += 4;
                available -= 4;
                return ((uint)ioBuffer[ioIndex++])
                    | (((uint)ioBuffer[ioIndex++]) << 8)
                    | (((uint)ioBuffer[ioIndex++]) << 16)
                    | (((uint)ioBuffer[ioIndex++]) << 24);
            case WireType.Fixed64:
                ulong val = ReadUInt64();
                checked { return (uint)val; }
            default:
                throw CreateException();
        }
    }

(ここでは wireType _broadly_はエンディアンなどの指標として機能しますが、それは重要ではありません)

`Fixed32`実装を見る:

  • `Ensure`は、少なくとも4バイト以上が確実に バッキングバッファー(必要に応じてさらにフェッチ)

  • 論理的な位置を追跡できるように、いくつかのカウンターをインクリメントします バッファ

  • バッファからデータを読み取ります_

フォーマットのリーダーをお持ちの方は、逆シリアル化がはるかに簡単になります。


0


いいえ、動作しません。 それは可能ですが、変換によるオーバーヘッドによりパフォーマンスが低下する可能性があります。