How to convert byte[] to int[]?
-
I am working with some data that is being passed to me in byte[]. However, the data actually represents an array of short(s) or an array of some other value types. For example, I get an array of 8 bytes, but I need to look at it as an array of 2 int(s). There have to be some kind of way to do the conversion, but I cannot seem to think of one. I could use some pointers... ;) Please let me know if you have any suggestions on what is the best way to convert byte arrays into arrays of other types. Thank you in advance. Kostya.
-
I am working with some data that is being passed to me in byte[]. However, the data actually represents an array of short(s) or an array of some other value types. For example, I get an array of 8 bytes, but I need to look at it as an array of 2 int(s). There have to be some kind of way to do the conversion, but I cannot seem to think of one. I could use some pointers... ;) Please let me know if you have any suggestions on what is the best way to convert byte arrays into arrays of other types. Thank you in advance. Kostya.
int[] Converter(byte[] ba) { int[] rtn = new int[ba.Length / 4]; int idx = 0; foreach (int x in rtn) { for (int i = 0; i < 4; i++) { x *= 256; x += ba[idx++]; } } return rtn; }
UNTESTED [edit]Forgot that return line[/edit] Paul
-
int[] Converter(byte[] ba) { int[] rtn = new int[ba.Length / 4]; int idx = 0; foreach (int x in rtn) { for (int i = 0; i < 4; i++) { x *= 256; x += ba[idx++]; } } return rtn; }
UNTESTED [edit]Forgot that return line[/edit] Paul
Thank you, Paul. I have tried one of this deals (the code you have suggested) before and it does work. The problem, however, is that I will have to write one of this for each data type (at least for about 10 of them). So, I was secretly hopping that someone will know of some
System.Magic.ConvertEverythingToEverything
kind of things... :) I guess, I am not that lucky... :) Thanks. Kostya. -
Thank you, Paul. I have tried one of this deals (the code you have suggested) before and it does work. The problem, however, is that I will have to write one of this for each data type (at least for about 10 of them). So, I was secretly hopping that someone will know of some
System.Magic.ConvertEverythingToEverything
kind of things... :) I guess, I am not that lucky... :) Thanks. Kostya.You could possibly use a class with FieldOffsetAttribute to replicate a C++ union; that might be a more flexible way of doing it.
[StructLayout(LayoutKind.Explicit)] public class Converter { [FieldOffset(0)] public byte[] byteArray; [FieldOffset(0)] public int intConverted; [FieldOffset(0)] public string stringConverted; // etc }
Maybe... Paul -
You could possibly use a class with FieldOffsetAttribute to replicate a C++ union; that might be a more flexible way of doing it.
[StructLayout(LayoutKind.Explicit)] public class Converter { [FieldOffset(0)] public byte[] byteArray; [FieldOffset(0)] public int intConverted; [FieldOffset(0)] public string stringConverted; // etc }
Maybe... PaulThank you. I will look into this.
-
Thank you, Paul. I have tried one of this deals (the code you have suggested) before and it does work. The problem, however, is that I will have to write one of this for each data type (at least for about 10 of them). So, I was secretly hopping that someone will know of some
System.Magic.ConvertEverythingToEverything
kind of things... :) I guess, I am not that lucky... :) Thanks. Kostya.Konstantin Vasserman wrote: System.Magic.ConvertEverythingToEverything kind of things... I guess, I am not that lucky... There is one, in a way :) Use the Marshal class in the following way. 1. Allocate a pointer to the size of your byte[]. Marshal.AllocHGlobal(). 2. Copy the byte[] to the pointer. Marshal.Copy(). 3. Copy the pointer to your selected array, eg int[] . Marshal.Copy(). 4. Free the pointer. Marshal.FreeHGlobal(). Hope you get what I am saying.. :) Before you criticize a man, walk a mile in his shoes. That way, when you do criticize him, you'll be a mile away and have his shoes.
-
Thank you, Paul. I have tried one of this deals (the code you have suggested) before and it does work. The problem, however, is that I will have to write one of this for each data type (at least for about 10 of them). So, I was secretly hopping that someone will know of some
System.Magic.ConvertEverythingToEverything
kind of things... :) I guess, I am not that lucky... :) Thanks. Kostya.This may not be the most efficient way of doing it, but it seems to work:
static Array ConvertByteArray(byte[] inArray, Type destType)
{
if (!destType.IsValueType)
throw new Exception("destType must be a value type!");// Can't calculate size for enum types. if (destType.IsEnum) destType = Enum.GetUnderlyingType(destType); int iSize = System.Runtime.InteropServices.Marshal.SizeOf(destType); if (iSize > 8) throw new Exception("destType is too large!"); System.Diagnostics.Debug.Assert( inArray.Length % iSize == 0, "Invalid array length!"); Array outArray = Array.CreateInstance( destType, inArray.Length / iSize); for (int i=0, j=0; i<inArray.Length && j<outArray.Length; i += iSize, j++) { // The value will not be larger than a UInt64. // NB: Left-shift doesn't work on 64-bit numbers. ulong val = 0; // Bytes from source array for (int k=0; k<iSize && i+k < inArray.Length; k++) val = (val \* 256) + inArray\[i + k\]; // Shouldn't happen, but just in case for (int k=inArray.Length - i; k < iSize; k++) val \*= 256; try { outArray.SetValue(Convert.ChangeType(val, destType), j); } catch (OverflowException ex) { // If destType is signed, we may have a negative value ulong iMask = (ulong)Math.Pow(2, 8 \* iSize - 1); if ((val & iMask) != 0) { // Try negative value. // NB: If destType is long, (long)iMask is negative // so just cast val to long. long val2; if ((long)iMask < 0) val2 = (long)val; else val2 = (long)(val & ~iMask) - (long)iMask; outArray.SetValue(Convert.ChangeType(val2, destType), j); } else // Not negative - just allow the // exception to propogate throw ex; } } return outArray;
}
If you know the type at compile-time, you can use:
byte[] a = new byte[6] {12, 34, 56, 78, 91, 111};
short[] b = (short[])ConvertByteArray(a, typeof(short));This code will test the function:
static void TestConvert(Type T)
{
int tSize;
if (T.IsEnum)
tSize = System.Runtime.In -
Konstantin Vasserman wrote: System.Magic.ConvertEverythingToEverything kind of things... I guess, I am not that lucky... There is one, in a way :) Use the Marshal class in the following way. 1. Allocate a pointer to the size of your byte[]. Marshal.AllocHGlobal(). 2. Copy the byte[] to the pointer. Marshal.Copy(). 3. Copy the pointer to your selected array, eg int[] . Marshal.Copy(). 4. Free the pointer. Marshal.FreeHGlobal(). Hope you get what I am saying.. :) Before you criticize a man, walk a mile in his shoes. That way, when you do criticize him, you'll be a mile away and have his shoes.
Interesting idea. :) Thank you.
-
This may not be the most efficient way of doing it, but it seems to work:
static Array ConvertByteArray(byte[] inArray, Type destType)
{
if (!destType.IsValueType)
throw new Exception("destType must be a value type!");// Can't calculate size for enum types. if (destType.IsEnum) destType = Enum.GetUnderlyingType(destType); int iSize = System.Runtime.InteropServices.Marshal.SizeOf(destType); if (iSize > 8) throw new Exception("destType is too large!"); System.Diagnostics.Debug.Assert( inArray.Length % iSize == 0, "Invalid array length!"); Array outArray = Array.CreateInstance( destType, inArray.Length / iSize); for (int i=0, j=0; i<inArray.Length && j<outArray.Length; i += iSize, j++) { // The value will not be larger than a UInt64. // NB: Left-shift doesn't work on 64-bit numbers. ulong val = 0; // Bytes from source array for (int k=0; k<iSize && i+k < inArray.Length; k++) val = (val \* 256) + inArray\[i + k\]; // Shouldn't happen, but just in case for (int k=inArray.Length - i; k < iSize; k++) val \*= 256; try { outArray.SetValue(Convert.ChangeType(val, destType), j); } catch (OverflowException ex) { // If destType is signed, we may have a negative value ulong iMask = (ulong)Math.Pow(2, 8 \* iSize - 1); if ((val & iMask) != 0) { // Try negative value. // NB: If destType is long, (long)iMask is negative // so just cast val to long. long val2; if ((long)iMask < 0) val2 = (long)val; else val2 = (long)(val & ~iMask) - (long)iMask; outArray.SetValue(Convert.ChangeType(val2, destType), j); } else // Not negative - just allow the // exception to propogate throw ex; } } return outArray;
}
If you know the type at compile-time, you can use:
byte[] a = new byte[6] {12, 34, 56, 78, 91, 111};
short[] b = (short[])ConvertByteArray(a, typeof(short));This code will test the function:
static void TestConvert(Type T)
{
int tSize;
if (T.IsEnum)
tSize = System.Runtime.InWow! :eek: I think I can adjust your code to work with my data. My byte arrays don't come in any predefined length. It might be a byte[1] that I need to read as byte, it might be byte[8] that is int[2] or byte[16] that is uint[4] and stuff like that. Anyway, your code will help me a lot. Thank you very much. :rose: