C# 将字节数组转换为C中类型未知的基元类型数组#
我有以下问题。我有一个字节数组,我想把它转换成一个基元类型数组。但我不知道是哪种类型。(这是作为类型数组给出的)。因此,我需要一个对象数组 当然,我可以在类型上使用开关(它们的数量有限),但我想知道是否有更好的解决方案 例如:C# 将字节数组转换为C中类型未知的基元类型数组#,c#,.net,bytearray,primitive-types,C#,.net,Bytearray,Primitive Types,我有以下问题。我有一个字节数组,我想把它转换成一个基元类型数组。但我不知道是哪种类型。(这是作为类型数组给出的)。因此,我需要一个对象数组 当然,我可以在类型上使用开关(它们的数量有限),但我想知道是否有更好的解决方案 例如: byte[] byteData = new byte[] {0xa0,0x14,0x72,0xbf,0x72,0x3c,0x21} Type[] types = new Type[] {typeof(int),typeof(short),typeof(sbyte)};
byte[] byteData = new byte[] {0xa0,0x14,0x72,0xbf,0x72,0x3c,0x21}
Type[] types = new Type[] {typeof(int),typeof(short),typeof(sbyte)};
//some algorithm
object[] primitiveData = {...};
//this array contains an the following elements
//an int converted from 0xa0,0x14,0x72,0xbf
//a short converted from 0x72, 0x3c
//a sbyte converted from 0x21
这有算法吗?或者我应该使用开关吗?以下是我的想法:
object[] primitiveData = new object[byteData.Lenght];
for (int i = 0; i < bytesData.Lenght; i++)
{
primitiveData[i] = Converter.ChangeType(bytesData[i], types[i]);
}
您可以使用反射来创建阵列并填充它们。(请注意由于SByte的数据错误而导致的错误处理程序):
[TestMethod]
公共void MyTestMethod(){
字节[]字节数据=新字节[]{0xa0,0x14,0x72,0xbf,0x72,0x3c,0x21};
类型[]类型=新类型[]{typeof(int)、typeof(short)、typeof(sbyte)};
列表结果=新列表();
foreach(类型中的变量类型){
Type arrayType=Type.MakeArrayType();
ConstructorInfo-ctor=arrayType.GetConstructor(新类型[]{typeof(int)});
Array Array=(Array)ctor.Invoke(新对象[]{byteData.Length});
for(int i=0;i
您可以使用:
此代码使用“不安全”来获取指向字节数组缓冲区的指针,但这应该不是问题 [编辑-注释后更改代码]
byte[] byteData = new byte[] { 0xa0, 0x14, 0x72, 0xbf, 0x72, 0x3c, 0x21 };
Type[] types = new Type[] { typeof(int), typeof(short), typeof(sbyte) };
object[] result = new object[types.Length];
unsafe
{
fixed (byte* p = byteData)
{
var localPtr = p;
for (int i = 0; i < types.Length; i++)
{
result[i] = Marshal.PtrToStructure((IntPtr)localPtr, types[i]);
localPtr += Marshal.SizeOf(types[i]);
}
}
}
byte[]byteData=新字节[]{0xa0、0x14、0x72、0xbf、0x72、0x3c、0x21};
类型[]类型=新类型[]{typeof(int)、typeof(short)、typeof(sbyte)};
object[]result=新对象[types.Length];
不安全的
{
固定(字节*p=字节数据)
{
var localPtr=p;
for(int i=0;i
有点脏,但它可以工作sp
用于指向在byteData
中从下一个读取的位置,我想可以通过其他方式检查类型。。。但这只是一个想法。所以,如果你不喜欢,请不要告诉我
byte[]byteData=新字节[]{0xa0、0x14、0x72、0xbf、0x72、0x3c、0x21};
类型[]类型=新类型[]{typeof(int)、typeof(short)、typeof(sbyte)};
object[]primitiveData=新对象[types.Length];
int sp=0;
对于(int i=0;iLooks OK,但您确实需要知道数据如何转换为字节[]。可能存在字节顺序问题。此解决方案(我认为)在字节数组上进行1对1映射。在这种情况下,我希望将n个字节映射到1个基元类型(其中n是基元类型的大小,以字节为单位(4表示int,2表示短,8表示浮点,…)。或者Convert类是否将数组用作指针?是否查找类型化数组或仅查找对象[]?仅查找对象[]我想用对象数组调用一个带有ConstructorInfo类的未知构造函数使用MemoryStream和指针似乎是一种浪费,而你只需要一个指向byteData
的指针就可以进行指针运算。@Ben:我同意,我很懒,我现在修改了它。
var dic = new Dictionary<Type, Func<byte, object>>
{
{ typeof(int), b => Convert.ToInt32(b) },
{ typeof(short), b => Convert.ToInt16(b) },
...
};
byte[] byteData = new byte[] { 0xa0, 0x14, 0x72, 0xbf, 0x72, 0x3c, 0x21 };
Type[] types = new Type[] { typeof(int), typeof(short), typeof(sbyte) };
List<object> list = new List<object>(primitiveData.Length);
for (int i = 0; i < primitiveData.Length; i++)
{
Byte b = byteData[i];
Type t = types[i];
Func<byte, object> func = dic[t];
list.Add(func(b));
}
object[] primitiveData = list.ToArray();
byte[] byteData = new byte[] { 0xa0, 0x14, 0x72, 0xbf, 0x72, 0x3c, 0x21 };
// delegates to converters instead of just appropriate types
Func<byte, object>[] funcs = new Func<byte, object>[]
{
b => Convert.ToInt32(b),
b => Convert.ToInt16(b),
b => Convert.ToSByte(b)
};
List<object> list = new List<object>(primitiveData.Length);
for (int i = 0; i < primitiveData.Length; i++)
{
Byte b = byteData[i];
Func<byte, object> func = funcs[i];
list.Add(func(b));
}
object[] primitiveData = list.ToArray();
byte[] byteData = new byte[] { 0xa0, 0x14, 0x72, 0xbf, 0x72, 0x3c, 0x21 };
Type[] types = new Type[] { typeof(int), typeof(short), typeof(sbyte) }; // asymmetric
int[] indexes = new int[] { 0, 0, 0, 0, 1, 2 }; // symmetric
[TestMethod]
public void MyTestMethod() {
byte[] byteData = new byte[] { 0xa0, 0x14, 0x72, 0xbf, 0x72, 0x3c, 0x21 };
Type[] types = new Type[] { typeof(int), typeof(short), typeof(sbyte) };
List<Array> result = new List<Array>();
foreach (var type in types) {
Type arrayType = type.MakeArrayType();
ConstructorInfo ctor = arrayType.GetConstructor(new Type[] { typeof(int) });
Array array = (Array)ctor.Invoke(new object[] { byteData.Length });
for (int i = 0; i < byteData.Length; i++) {
byte b = byteData[i];
try {
array.SetValue(Convert.ChangeType(b, type), i);
} catch {
Console.WriteLine("Error with type {0} and value {1}", type, b);
}
}
result.Add(array);
}
// -------------------
// show result
foreach (var array in result) {
Console.WriteLine(array.GetType());
foreach (var item in array) {
Console.WriteLine(" {0}", item);
}
}
}
public static IEnumerable<object> ConvertToObjects(byte[] byteData, Type[] types)
{
using (var stream = new MemoryStream(byteData))
using (var reader = new BinaryReader(stream))
{
foreach (var type in types)
{
if (type == typeof(short))
{
yield return reader.ReadInt16();
}
else if (type == typeof(int))
{
yield return reader.ReadInt32();
}
else if (type == typeof(sbyte))
{
yield return reader.ReadSByte();
}
// ... other types
else
{
throw new NotSupportedException(string.Format("{0} is not supported", type));
}
}
}
}
byte[] byteData = new byte[] { 0xa0, 0x14, 0x72, 0xbf, 0x72, 0x3c, 0x21 };
Type[] types = new Type[] { typeof(int), typeof(short), typeof(sbyte) };
object[] result = ConvertToObjects(byteData, types).ToArray();
byte[] byteData = new byte[] { 0xa0, 0x14, 0x72, 0xbf, 0x72, 0x3c, 0x21 };
Type[] types = new Type[] { typeof(int), typeof(short), typeof(sbyte) };
object[] result = new object[types.Length];
unsafe
{
fixed (byte* p = byteData)
{
var localPtr = p;
for (int i = 0; i < types.Length; i++)
{
result[i] = Marshal.PtrToStructure((IntPtr)localPtr, types[i]);
localPtr += Marshal.SizeOf(types[i]);
}
}
}
byte[] byteData = new byte[] { 0xa0, 0x14, 0x72, 0xbf, 0x72, 0x3c, 0x21 };
Type[] types = new Type[] {typeof(int),typeof(short),typeof(sbyte)};
object[] primitiveData = new object[types.Length];
int sp = 0;
for(int i=0; i<types.Length; i++)
{
string s = types[i].FullName;
switch(types[i].FullName)
{
case "System.Int32":{
primitiveData[i] = BitConverter.ToInt32(byteData, sp);
sp += 4;
}break;
case "System.Int16":
{
primitiveData[i] = BitConverter.ToInt16(byteData, sp);
sp += 2;
}break;
case "System.SByte":
{
primitiveData[i] = (sbyte)byteData[sp];
sp += 1;
}break;
}
}