バイナリ ファイルから一連の値を読み込もうとしていますが、実行時まで値の型がわかりません。
簡単な例
長さが 10 バイトのバイナリ ファイルがあります。バイトは、順に an int
、 a float
、および a を表しますshort
。私はコンパイル時にこれを知りませんが、実行時には次のような配列でこれを知っています:
Type[] types = new Type[3];
types[0] = typeof(int);
types[1] = typeof(float);
types[2] = typeof(short);
質問
このリストを取得したので、この情報を使用してファイルから値をすばやく読み取る方法はありますか? 私が考えることができる唯一の方法は、大きなif
ブロックを使用することですが、それは本当に醜いです:
for (int i = 0; i < types.Length; i++)
{
if (types[i] == typeof(int))
{
int val = binaryfile.ReadInt32();
//... etc ...
}
else if (types[i] == typeof(float))
{
float val = binaryfile.ReadSingle();
//... etc ...
}
else if //... etc...
}
しかし、これは醜く面倒です。Type
配列内の情報を使用して、types
何らかの形でこれを「自動化」できるかどうか疑問に思っています。
私が試したこと
私が考えたアイデアの 1 つは、生のバイトを配列に読み込んでから、バイト配列で変換を実行することでした。それでは、私の配列が次のようになっているとしましょう:
byte[] buf = new byte[10] {
0x40, 0xE2, 0x01, 0x00,
0x79, 0xE9, 0xF6, 0x42,
0x39, 0x30 };
これにはint
、、、float
およびshort
値 123456、123.456、および 12345 がそれぞれ含まれます。これで、次のことができます。
fixed (byte* bp = &buf[0])
{
int* ip = (int*)bp;
Console.WriteLine("int ptr: {0}", *ip);
}
これはうまく機能しているように見えますが、次の 2 つの問題があります。
*ip
マネージド ドメインにマーシャリングする方法がわかりません。次のように、タイプリストをまだ使用できません。
fixed (byte* bp = &buf[0]) { (types[0])* ip = ((types[0])*)bp; // both errors here Console.WriteLine("int ptr: {0}", *ip); }
これにより、次の行で 2 つのコンパイル時エラーが発生します。
Error 1 Invalid expression term ')'
Error 2 ) expected
試してみようと思ったのはここまでです。
誰かが助けてくれることを願っています。人生をずっと楽にしてくれるシンプルなものが欠けているように感じます。
アップデート
if
Peter Duniho の提案を試してみましたが、大きなブロックに比べてパフォーマンスの低下はわずかですが、うまく機能しているようです。
〜 100 MB のファイルからのいくつかの結果を次に示します (すべての時間はミリ秒単位です)。
ピーターの方法:
2025
2003
1954
1979
1958
if
ブロック:
1531
1488
1486
1489
if
それほど重要なことはありませんが、私ははるかに大きなファイル (GB 範囲) で作業する予定なので、これらの数百ミリ秒が加算されるため、同じくらい高速なものが見つかるまで、醜いブロックを使い続けるつもりです。