我试图从二进制文件中读取一系列值,但直到运行时我才知道值类型是什么。
我有一个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
信息以某种方式&#34;自动化&#34;此
我想到的一个想法是将原始字节读入数组,然后在字节数组上执行转换。所以,让我们说我的数组看起来像这样:
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文件的一些结果(所有时间都以毫秒为单位):
彼得的方法:
2025
2003
1954
1979
1958
if
阻止:
1531
1488
1486
1489
没有什么太重要的,虽然因为我计划使用更大,更大的文件(在GB范围内),这几百毫秒加起来,所以我会坚持使用丑陋的if
块直到我找到一些快速的东西。
答案 0 :(得分:1)
我不是百分百肯定我明白你实际上试图解决这个问题的哪一部分。但根据我的想法,我就是这样做的:
class Program
{
static readonly Dictionary<Type, Func<byte[], int, Tuple<object, int>>> _converters =
new Dictionary<Type, Func<byte[], int, Tuple<object, int>>>
{
{ typeof(int), (rgb, ib) =>
Tuple.Create((object)BitConverter.ToInt32(rgb, ib), sizeof(int)) },
{ typeof(float), (rgb, ib) =>
Tuple.Create((object)BitConverter.ToSingle(rgb, ib), sizeof(float)) },
{ typeof(short), (rgb, ib) =>
Tuple.Create((object)BitConverter.ToInt16(rgb, ib), sizeof(short)) },
};
static void Main(string[] args)
{
Type[] typeMap = { typeof(int), typeof(float), typeof(short) };
byte[] inputBuffer =
{ 0x40, 0xE2, 0x01, 0x00, 0x79, 0xE9, 0xF6, 0x42, 0x39, 0x30 };
int ib = 0, objectIndex = 0;
while (ib < inputBuffer.Length)
{
Tuple<object, int> current =
_converters[typeMap[objectIndex++]](inputBuffer, ib);
Console.WriteLine("Value: " + current.Item1);
ib += current.Item2;
}
}
}