Опитвам се да прочета поредица от стойности от двоичен файл, но няма да знам какви са типовете стойности до момента на изпълнение.
Опростен пример
Имам двоичен файл с дължина 10 байта. Байтовете представляват по ред int
, float
и 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
, за да "автоматизирам" по някакъв начин това.
Това, което съм пробвал
Една идея, за която се сетих, беше да прочета необработените байтове в масив, след което да извърша преобразуването върху масива от байтове. Да кажем, че моят масив изглежда така:
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);
}
Изглежда, че това работи добре, но има два проблема:
- Не знам как да маршалирам
*ip
обратно към управлявания домейн. Все още не мога да използвам моя списък с типове, както следва:
fixed (byte* bp = &buf[0]) { (types[0])* ip = ((types[0])*)bp; // both errors here Console.WriteLine("int ptr: {0}", *ip); }
Това създава две грешки по време на компилиране на посочения ред:
Error 1 Invalid expression term ')'
Error 2 ) expected
Това е всичко, което съм мислил да опитам досега.
Надявам се някой да помогне. Имам чувството, че ми липсва нещо просто, което би направило живота ми много по-лесен.
Актуализация
Опитах предложението на Peter Duniho и изглежда, че работи доста добре, въпреки че има малък удар в производителността в сравнение с голям блок if
.
Ето някои резултати от ~100 MB файл (всички времена са в ms):
Методът на Петър:
2025
2003
1954
1979
1958
if
блок:
1531
1488
1486
1489
Нищо особено важно, въпреки че тъй като планирам да работя с много, много по-големи файлове (в диапазона GB), тези няколкостотин милисекунди се натрупват, така че ще се придържам към грозния блок if
, докато не намеря нещо толкова бързо.