I have an object with a Property of type byte[,,*]
now i'd like to use System.Random::NextBytes() to fill this multidimensional array with random values.
NextBytes however takes an argument of byte[]
can i cast the multidimensional array somehow to the singledimensional one in order to pass it as an argument?
thanks!
You can't cast it, but you can copy the values quickly from a normal byte[] to a byte[,,] using Buffer.BlockCopy. So you'll have to allocate a normal byte array to start with, then copy the results over.
Sample:
using System;
class Test
{
static void Main()
{
Random rng = new Random();
byte[,,] y = new byte[2,2,2];
FillArray(y, rng);
foreach (byte b in y)
{
Console.WriteLine(b);
}
}
static void FillArray(byte[,,] array, Random rng)
{
byte[] tmp = new byte[array.Length];
rng.NextBytes(tmp);
Buffer.BlockCopy(tmp, 0, array, 0, tmp.Length);
}
}
Related
I have an int array of bits (length always 64) like:
1110000100000110111001000001110010011000110011111100001011100100
and I want to write it in one Int64 (or ulong?) variable. How to do it?
I tried to create a BitArray and then get int, but it throws System.ArgumentException, on CopyTo line:
private static Int64 GetIntFromBitArray(BitArray bitArray) {
var array = new Int64[1];
bitArray.CopyTo(array, 0);
return array[0];
}
That is because as mentioned in the documentation,
The specified array must be of a compatible type. Only bool, int, and byte types of arrays are supported.
So you could do something like this: (not tested)
private static long GetIntFromBitArray(BitArray bitArray)
{
var array = new byte[8];
bitArray.CopyTo(array, 0);
return BitConverter.ToInt64(array, 0);
}
Looking at the implementation of BitArray.CopyTo, it would be faster to copy the bits into an int[] (and then build the long from its two halves), that could look something like this: (also not tested)
private static long GetIntFromBitArray(BitArray bitArray)
{
var array = new int[2];
bitArray.CopyTo(array, 0);
return (uint)array[0] + ((long)(uint)array[1] << 32);
}
Casts to uint are to prevent sign-extension.
I have to do a program that read and image and puts it into a byte array
var Imagenoriginal = File.ReadAllBytes("10M.bmp");
And Divide That byte Array into 3 Diferent Arrays in order to send each one of this new arrays to other computer ( Using Pipes ) to process them there and finally take them back to the origial computer and finally give the result.
But my question Is how do I do an Algorithm able to divide the byte array in three different bytes arrays if the image selected can have diferent size.
Thanks for your help, have a nice day. =)
You can divide length of array, so you have three integers n1, n2 and n3 with all of them summing up to array.Length. Then, this snippet, using LINQ should be of help:
var arr1 = sourceArray.Take(n1).ToArray();
var arr2 = sourceArray.Skip(n1).Take(n2).ToArray();
var arr3 = sourceArray.Skip(n1+n2).Take(n3).ToArray();
Now, in arr1,arr2 and arr3 you will have three parts of your source array. You need to use LINQ, so in the beginning of the code don't forget using System.Linq;.
You can try like this:
public static IEnumerable<IEnumerable<T>> DivideArray<T>(this T[] array, int size)
{
for (var i = 0; i < (float)array.Length / size; i++)
{
yield return array.Skip(i * size).Take(size);
}
}
The call like this:
var arr = new byte[] {1, 2, 3, 4, 5,6};
var dividedArray = arr.DivideArray(3);
Here is a LINQ approach:
public List<List<byte>> DivideArray(List<byte> arr)
{
return arr
.Select((x, i) => new { Index = i, Value = x })
.GroupBy(x => x.Index / 100)
.Select(x => x.Select(v => v.Value).ToList())
.ToList();
}
Have you considered using Streams? You could extend the Stream class to provide the desired behavior, as follows:
public static class Utilities
{
public static IEnumerable<byte[]> ReadBytes(this Stream input, long bufferSize)
{
byte[] buffer = new byte[bufferSize];
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
using (MemoryStream tempStream = new MemoryStream())
{
tempStream.Write(buffer, 0, read);
yield return tempStream.ToArray();
}
}
}
public static IEnumerable<byte[]> ReadBlocks(this Stream input, int nblocks)
{
long bufferSize = (long)Math.Ceiling((double)input.Length / nblocks);
return input.ReadBytes(bufferSize);
}
}
The ReadBytes extension method reads the input Stream and returns its data as a sequence of byte arrays, using the specified bufferSize.
The ReadBlocks extension method calls ReadBytes with the appropriate buffer size, so that the number of elements in the sequence equals nblocks.
You could then use ReadBlocks to achieve what you want:
public class Program
{
static void Main()
{
FileStream inputStream = File.Open(#"E:\10M.bmp", FileMode.Open);
const int nblocks = 3;
foreach (byte[] block in inputStream.ReadBlocks(nblocks))
{
Console.WriteLine("{0} bytes", block.Length);
}
}
}
Note how ReadBytes uses tempStream and read to write in memory the bytes read from the input stream before converting them into an array of bytes, it solves the problem with the leftover bytes mentioned in the comments.
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;
}
// ******************************************************************
I have a string array I need to convert to byte[][] (to connect Xcode with Unity scripts in C#).
This is the functions in Xcode:
void doThisC(char** matrix);
And in Unity in C#, this is what I have but I'm not able to make it work:
public static void doThis(string[] array, int size){
char[][] grid = new char[][] { new char[size] , new char[100]};
byte[][] buffer;
for(int i = 0 ; i < size ; i++)
{
grid[i] = array[i].ToString().ToCharArray();
buffer[i] = (new System.Text.UTF8Encoding()).GetBytes(grid[i]);
}
doThisC(buffer);
}
The grid array only has two items, so the code will only work up to two strings. You don't need the grid array at all. Also, you don't create the array buffer:
public static void doThis(string[] array){
byte[][] buffer = new byte[array.Length][];
for(int i = 0 ; i < array.Length ; i++)
{
buffer[i] = System.Text.Encoding.UTF8.GetBytes(array[i]);
}
doThisC(buffer);
}
or using Linq extension methods:
public static void doThis(string[] array){
byte[][] buffer = array.Select(System.Text.Encoding.UTF8.GetBytes).ToArray();
doThisC(buffer);
}
I think your problem is just with array creation, you should first create a byte array properly:
byte[][] buffer = new byte[size][];
In your current implementation, when you call buffer[i] you will get an exception, but you can fix it with little change as mentioned above. Other parts of your code (depending to your encoding), seems correct.
How to add a byte to the beginning of an existing byte array?
My goal is to make array what's 3 bytes long to 4 bytes. So that's why I need to add 00 padding in the beginning of it.
You can't do that. It's not possible to resize an array. You have to create a new array and copy the data to it:
bArray = AddByteToArray(bArray, newByte);
code:
public byte[] AddByteToArray(byte[] bArray, byte newByte)
{
byte[] newArray = new byte[bArray.Length + 1];
bArray.CopyTo(newArray, 1);
newArray[0] = newByte;
return newArray;
}
As many people here have pointed out, arrays in C#, as well as in most other common languages, are statically sized. If you're looking for something more like PHP's arrays, which I'm just going to guess you are, since it's a popular language with dynamically sized (and typed!) arrays, you should use an ArrayList:
var mahByteArray = new ArrayList<byte>();
If you have a byte array from elsewhere, you can use the AddRange function.
mahByteArray.AddRange(mahOldByteArray);
Then you can use Add() and Insert() to add elements.
mahByteArray.Add(0x00); // Adds 0x00 to the end.
mahByteArray.Insert(0, 0xCA) // Adds 0xCA to the beginning.
Need it back in an array? .ToArray() has you covered!
mahOldByteArray = mahByteArray.ToArray();
Arrays can't be resized, so you need to allocte a new array that is larger, write the new byte at the beginning of it, and use Buffer.BlockCopy to transfer the contents of the old array across.
To prevent recopy the array every time which isn't efficient
What about using Stack
csharp> var i = new Stack<byte>();
csharp> i.Push(1);
csharp> i.Push(2);
csharp> i.Push(3);
csharp> i; { 3, 2, 1 }
csharp> foreach(var x in i) {
> Console.WriteLine(x);
> }
3
2
1
Although internally it creates a new array and copies values into it, you can use Array.Resize<byte>() for more readable code. Also you might want to consider checking the MemoryStream class depending on what you're trying to achieve.
Simple, just use the code below, as I do:
public void AppendSpecifiedBytes(ref byte[] dst, byte[] src)
{
// Get the starting length of dst
int i = dst.Length;
// Resize dst so it can hold the bytes in src
Array.Resize(ref dst, dst.Length + src.Length);
// For each element in src
for (int j = 0; j < src.Length; j++)
{
// Add the element to dst
dst[i] = src[j];
// Increment dst index
i++;
}
}
// Appends src byte to the dst array
public void AppendSpecifiedByte(ref byte[] dst, byte src)
{
// Resize dst so that it can hold src
Array.Resize(ref dst, dst.Length + 1);
// Add src to dst
dst[dst.Length - 1] = src;
}
I think it is a more complete function
/// <summary>
/// add a new byte to end or start of a byte array
/// </summary>
/// <param name="_input_bArray"></param>
/// <param name="_newByte"></param>
/// <param name="_add_to_start_of_array">if this parameter is True then the byte will be added to the beginning of array otherwise
/// to the end of the array</param>
/// <returns>result byte array</returns>
public byte[] addByteToArray(byte[] _input_bArray, byte _newByte, Boolean _add_to_start_of_array)
{
byte[] newArray;
if (_add_to_start_of_array)
{
newArray = new byte[_input_bArray.Length + 1];
_input_bArray.CopyTo(newArray, 1);
newArray[0] = _newByte;
}
else
{
newArray = new byte[_input_bArray.Length + 1];
_input_bArray.CopyTo(newArray, 0);
newArray[_input_bArray.Length] = _newByte;
}
return newArray;
}