Okay, I'm trying to convert a byte[] to a short[], or Int16[].
List<Int16[]> lol = new List<Int16[]>();
byte[] b = System.Text.Encoding.Default.GetBytes("lolololololololololololoolol");
lol.Add(Convert.ToInt16(b));
MessageBox.Show(Encoding.Default.GetString(Encoding.Default.GetBytes(lol[0])));
That is something that I tried, but obviously, it doesn't work. So how would I do this?
It looks to me like you want to convert an entire array in one line. It could be done like this:
List<Int16[]> lol = new List<Int16[]>();
byte[] b = System.Text.Encoding.Default.GetBytes("lolololololololololololoolol");
lol.Add(Array.ConvertAll(b, x => Convert.ToInt16(x)));
You have to go through the byte array, and convert each element.
List<Int16[]> lol=new List<Int16[]>();
byte [] b=System.Text.Encoding.Default.GetBytes("lolololololololololololoolol");
Int16 [] a=new Int16 [b.Length];
for (Int32 i=0;i<a.Length;++i) {
a[i]=Convert.ToInt16(b[i]);
}
lol.Add(a);
You probably want BitConverter.ToInt16(), which you'd need to call for each pair of bytes.
Or, use Buffer.BlockCopy to do it all at once (using the machine's native byte order).
byte[] by = new byte[5];
short[] sh = new short[5];
by[0] = 0x1;
by[1] = 0x2;
by[2] = 0x3;
by[3] = 0x4;
by[4] = 0x5;
for (int x = 0; x < sh.GetLength(0); x++)
{
sh[x] = by[x];
MessageBox.Show(by[x].ToString());
That worked for me. Not sure if I am misunderstanding or not.
Related
This might be a simple one, but I can't seem to find an easy way to do it. I need to save an array of 84 uint's into an SQL database's BINARY field. So I'm using the following lines in my C# ASP.NET project:
//This is what I have
uint[] uintArray;
//I need to convert from uint[] to byte[]
byte[] byteArray = ???
cmd.Parameters.Add("#myBindaryData", SqlDbType.Binary).Value = byteArray;
So how do you convert from uint[] to byte[]?
How about:
byte[] byteArray = uintArray.SelectMany(BitConverter.GetBytes).ToArray();
This'll do what you want, in little-endian format...
You can use System.Buffer.BlockCopy to do this:
byte[] byteArray = new byte[uintArray.Length * 4];
Buffer.BlockCopy(uintArray, 0, byteArray, 0, uintArray.Length * 4];
http://msdn.microsoft.com/en-us/library/system.buffer.blockcopy.aspx
This will be much more efficient than using a for loop or some similar construct. It directly copies the bytes from the first array to the second.
To convert back just do the same thing in reverse.
There is no built-in conversion function to do this. Because of the way arrays work, a whole new array will need to be allocated and its values filled-in. You will probably just have to write that yourself. You can use the System.BitConverter.GetBytes(uint) function to do some of the work, and then copy the resulting values into the final byte[].
Here's a function that will do the conversion in little-endian format:
private static byte[] ConvertUInt32ArrayToByteArray(uint[] value)
{
const int bytesPerUInt32 = 4;
byte[] result = new byte[value.Length * bytesPerUInt32];
for (int index = 0; index < value.Length; index++)
{
byte[] partialResult = System.BitConverter.GetBytes(value[index]);
for (int indexTwo = 0; indexTwo < partialResult.Length; indexTwo++)
result[index * bytesPerUInt32 + indexTwo] = partialResult[indexTwo];
}
return result;
}
byte[] byteArray = Array.ConvertAll<uint, byte>(
uintArray,
new Converter<uint, byte>(
delegate(uint u) { return (byte)u; }
));
Heed advice from #liho1eye, make sure your uints really fit into bytes, otherwise you're losing data.
If you need all the bits from each uint, you're gonna to have to make an appropriately sized byte[] and copy each uint into the four bytes it represents.
Something like this ought to work:
uint[] uintArray;
//I need to convert from uint[] to byte[]
byte[] byteArray = new byte[uintArray.Length * sizeof(uint)];
for (int i = 0; i < uintArray.Length; i++)
{
byte[] barray = System.BitConverter.GetBytes(uintArray[i]);
for (int j = 0; j < barray.Length; j++)
{
byteArray[i * sizeof(uint) + j] = barray[j];
}
}
cmd.Parameters.Add("#myBindaryData", SqlDbType.Binary).Value = byteArray;
Say I have an array like this:
byte[] arr = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}
Can I somehow iterate through it with elements treated like Uint16? I want to make my application to treat it like {0x1122, 0x3344, 0x5566, 0x7788}.
Tried using as keyword but the compiler woudn't let me:
byte[] bytearray = new byte[10];
UInt16[] uint16array = bytearray as UInt16[];
Is there any way to do it? (without creating another array or casting two bytes into one uint16 every iteration)
this little helper method should help you
public static class helper
{
public static UInt16[] ToUnit16(this byte[] arr)
{
if (arr == null)
return null;
var len = arr.Length;
if ((len % 2) != 0)
throw new ArgumentException("Must divide by 2");
var count = len / 2;
var result = new UInt16[count];
do
{
result[--count] = (UInt16)((arr[--len]) | arr[--len] << 8);
} while (count > 0);
return result;
}
}
No, C# doesn't offer a way to safely reinterpret one object as if it were some different type of object (you can do it with unsafe code, but then the whole assembly winds up "unsafe").
You can use BitConverter.ToUInt16(), or even wrap the byte[] in a MemoryStream and use the BinaryReader.ReadUInt16() method to read from the byte[] object. But judging from the wording of the question, you don't want to use any method like that.
You can do it with unsafe code:
fixed(byte* p = bytearray)
{
ushort* ptr=(ushort*)p;
for(int i = 0; i < bytearray.Length/2; i++)
{
//...
}
}
You cannot cast the entire array like that, at least not in managed code. You can convert this using BitConverter.ToUInt16, like this:
UInt16[] uint16array = Enumerable
.Range(0, arr.Length/2)
.Select(i => BitConverter.ToUInt16(arr, 2*i))
.ToArray();
I would like to save a Color[] to a file. To do so, I found that saving a byte array to a file using "System.IO.File.WriteAllBytes" should be very efficient.
I would like to cast my Color[] (array of struct) to a byte array into a safe way considering:
Potential problem of little endian / big endian (I think it is impossible to happen but want to be sure)
Having 2 differents pointer to the same memory which point to different type. Does the garbage collection will know what to do - moving objects - deleting a pointer ???
If it is possible, it would be nice to have a generic way to cast array of byte to array of any struct (T struct) and vice-versa.
If not possible, why ?
Thanks,
Eric
I think that those 2 solutions make a copy that I would like to avoid and also they both uses Marshal.PtrToStructure which is specific to structure and not to array of structure:
Reading a C/C++ data structure in C# from a byte array
How to convert a structure to a byte array in C#?
Since .NET Core 2.1, yes we can! Enter MemoryMarshal.
We will treat our Color[] as a ReadOnlySpan<Color>. We reinterpret that as a ReadOnlySpan<byte>. Finally, since WriteAllBytes has no span-based overload, we use a FileStream to write the span to disk.
var byteSpan = MemoryMarshal.AsBytes(colorArray.AsSpan());
fileStream.Write(byteSpan);
As an interesting side note, you can also experiment with the [StructLayout(LayoutKind.Explicit)] as an attribute on your fields. It allows you to specify overlapping fields, effectively allowing the concept of a union.
Here is a blog post on MSDN that illustrates this. It shows the following code:
[StructLayout(LayoutKind.Explicit)]
public struct MyUnion
{
[FieldOffset(0)]
public UInt16 myInt;
[FieldOffset(0)]
public Byte byte1;
[FieldOffset(1)]
public Byte byte2;
}
In this example, the UInt16 field overlaps with the two Byte fields.
This seems to be strongly related to what you are trying to do. It gets you very close, except for the part of writing all the bytes (especially of multiple Color objects) efficiently. :)
Regarding Array Type Conversion
C# as a language intentionally makes the process of flattening objects or arrays into byte arrays difficult because this approach goes against the principals of .NET strong typing. The conventional alternatives include several serialization tools which are generally seen a safer and more robust, or manual serialization coding such as BinaryWriter.
Having two variables of different types point to the same object in memory can only be performed if the types of the variables can be cast, implicitly or explicitly. Casting from an array of one element type to another is no trivial task: it would have to convert the internal members that keep track of things such as array length, etc.
A simple way to write and read Color[] to file
void WriteColorsToFile(string path, Color[] colors)
{
BinaryWriter writer = new BinaryWriter(File.OpenWrite(path));
writer.Write(colors.Length);
foreach(Color color in colors)
{
writer.Write(color.ToArgb());
}
writer.Close();
}
Color[] ReadColorsFromFile(string path)
{
BinaryReader reader = new BinaryReader(File.OpenRead(path));
int length = reader.ReadInt32();
Colors[] result = new Colors[length];
for(int n=0; n<length; n++)
{
result[n] = Color.FromArgb(reader.ReadInt32());
}
reader.Close();
}
You could use pointers if you really want to copy each byte and not have a copy but the same object, similar to this:
var structPtr = (byte*)&yourStruct;
var size = sizeof(YourType);
var memory = new byte[size];
fixed(byte* memoryPtr = memory)
{
for(int i = 0; i < size; i++)
{
*(memoryPtr + i) = *structPtr++;
}
}
File.WriteAllBytes(path, memory);
I just tested this and after adding the fixed block and some minor corrections it looks like it is working correctly.
This is what I used to test it:
public static void Main(string[] args)
{
var a = new s { i = 1, j = 2 };
var sPtr = (byte*)&a;
var size = sizeof(s);
var mem = new byte[size];
fixed (byte* memPtr = mem)
{
for (int i = 0; i < size; i++)
{
*(memPtr + i) = *sPtr++;
}
}
File.WriteAllBytes("A:\\file.txt", mem);
}
struct s
{
internal int i;
internal int j;
}
The result is the following:
(I manually resolved the hex bytes in the second line, only the first line was produced by the program)
public struct MyX
{
public int IntValue;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U1)]
public byte[] Array;
MyX(int i, int b)
{
IntValue = b;
Array = new byte[3];
}
public MyX ToStruct(byte []ar)
{
byte[] data = ar;//= { 1, 0, 0, 0, 9, 8, 7 }; // IntValue = 1, Array = {9,8,7}
IntPtr ptPoit = Marshal.AllocHGlobal(data.Length);
Marshal.Copy(data, 0, ptPoit, data.Length);
MyX x = (MyX)Marshal.PtrToStructure(ptPoit, typeof(MyX));
Marshal.FreeHGlobal(ptPoit);
return x;
}
public byte[] ToBytes()
{
Byte[] bytes = new Byte[Marshal.SizeOf(typeof(MyX))];
GCHandle pinStructure = GCHandle.Alloc(this, GCHandleType.Pinned);
try
{
Marshal.Copy(pinStructure.AddrOfPinnedObject(), bytes, 0, bytes.Length);
return bytes;
}
finally
{
pinStructure.Free();
}
}
}
void function()
{
byte[] data = { 1, 0, 0, 0, 9, 8, 7 }; // IntValue = 1, Array = {9,8,7}
IntPtr ptPoit = Marshal.AllocHGlobal(data.Length);
Marshal.Copy(data, 0, ptPoit, data.Length);
var x = (MyX)Marshal.PtrToStructure(ptPoit, typeof(MyX));
Marshal.FreeHGlobal(ptPoit);
var MYstruc = x.ToStruct(data);
Console.WriteLine("x.IntValue = {0}", x.IntValue);
Console.WriteLine("x.Array = ({0}, {1}, {2})", x.Array[0], x.Array[1], x.Array[2]);
}
Working code for reference (take care, I did not need the alpha channel in my case):
// ************************************************************************
// If someday Microsoft make Color serializable ...
//public static void SaveColors(Color[] colors, string path)
//{
// BinaryFormatter bf = new BinaryFormatter();
// MemoryStream ms = new MemoryStream();
// bf.Serialize(ms, colors);
// byte[] bytes = ms.ToArray();
// File.WriteAllBytes(path, bytes);
//}
// If someday Microsoft make Color serializable ...
//public static Colors[] LoadColors(string path)
//{
// Byte[] bytes = File.ReadAllBytes(path);
// BinaryFormatter bf = new BinaryFormatter();
// MemoryStream ms2 = new MemoryStream(bytes);
// return (Colors[])bf.Deserialize(ms2);
//}
// ******************************************************************
public static void SaveColorsToFile(Color[] colors, string path)
{
var formatter = new BinaryFormatter();
int count = colors.Length;
using (var stream = File.OpenWrite(path))
{
formatter.Serialize(stream, count);
for (int index = 0; index < count; index++)
{
formatter.Serialize(stream, colors[index].R);
formatter.Serialize(stream, colors[index].G);
formatter.Serialize(stream, colors[index].B);
}
}
}
// ******************************************************************
public static Color[] LoadColorsFromFile(string path)
{
var formatter = new BinaryFormatter();
Color[] colors;
using (var stream = File.OpenRead(path))
{
int count = (int)formatter.Deserialize(stream);
colors = new Color[count];
for (int index = 0; index < count; index++)
{
byte r = (byte)formatter.Deserialize(stream);
byte g = (byte)formatter.Deserialize(stream);
byte b = (byte)formatter.Deserialize(stream);
colors[index] = Color.FromRgb(r, g, b);
}
}
return colors;
}
// ******************************************************************
How to Convert a byte array into an int array? I have a byte array holding 144 items and the ways I have tried are quite inefficient due to my inexperience. I am sorry if this has been answered before, but I couldn't find a good answer anywhere.
Simple:
//Where yourBytes is an initialized byte array.
int[] bytesAsInts = yourBytes.Select(x => (int)x).ToArray();
Make sure you include System.Linq with a using declaration:
using System.Linq;
And if LINQ isn't your thing, you can use this instead:
int[] bytesAsInts = Array.ConvertAll(yourBytes, c => (int)c);
I known this is an old post, but if you were looking in the first place to get an array of integers packed in a byte array (and it could be considering your array byte of 144 elements), this is a way to do it:
var size = bytes.Count() / sizeof (int);
var ints = new int[size];
for (var index = 0; index < size; index++)
{
ints[index] = BitConverter.ToInt32(bytes, index * sizeof (int));
}
Note: take care of the endianness if needed. (And in most case it will)
Use Buffer.BlockCopy instead of Array.ConvertAll.
ref Converting an int[] to byte[] in C#
byte[] bytes = new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 };
int[] ints= Array.ConvertAll(bytes, Convert.ToInt32);
will return ints[]={0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
not return ints[]={0x04030201,0x08070605}
should use
Buffer.BlockCopy(bytes, 0, ints, 0, bytes.Length);
Now It's Simple like follows,
int[] result = Array.ConvertAll(bytesArray, Convert.ToInt32);
I want to add a byte array to a short var.
Can any one suggest how to do using bit wise operators.
For example:
byte[] a = new byte[] { 0x02,0x11 }; //Dec eq is 529
short b = 10;
I want the result to be 539.
b += ((short) a[0]) << 8;
b += a[1];
I know you have a byte array and not a BitArray, but maybe this helps.
short c = (short)(BitConverter.ToInt16(a, 0) + b);