Working on Windows OS and C# (means little endian) so no need for extra checks.
How can I increase speed of reversing an array of bytes using pointers?
Instead of a normal for loop:
const int value = 133;
var bArr = new byte[]{ 0, 0, 0 , value };
int Len = bArr.Length;
var rrAb = new byt[Len];
for(int idx=0; idx<bArr.Length;idx++)
rrAb[idx] = bArr[--Len];
String reverse using pointers
Related
Can someone explain how I can convert a float(Vector3.x) to a byte array with c# and decode it with node js?
I read on the internet that Vector3.x is a system.single data type and use 4 bytes(32 bits). I use BitConverter to convert it to a byte array. With Nodejs I use readFloatBE().
I don`t know what I'm doing wrong, but I get constantly a bad result with node js with console.log().
Unity csharp:
public static int FloatToBit(int offset, ref byte[] data, Single number)
{
byte[] byteArray = System.BitConverter.GetBytes(number);
for (int i = 0;i<4;i++)
{
data[offset + i] = byteArray[i];
}
return 4;
}
Node js
readFloat: function (offset, data) {
var b = new Buffer(4);
for (var i = 0; i < 4; i++) {
b[i] = data[offset + i];
}
return data.readFloatLE(b, 0);
},
If I send -2.5, unity output is: 0 0 32 191 with -1 unity output is: 0 0 128 192
Nodejs output with readFloatLE: 3.60133705331478e-43
Here's a working set of data from front to back.
C#:
Single fl = 2.5F;
var bytes = System.BitConverter.GetBytes(fl);
var str = BitConverter.ToString(bytes); // 00-00-20-40
Nodejs:
let buffer = Buffer.from([ 0x00, 0x00, 0x20, 0x40 ]);
let float = buffer.readFloatLE(); // 2.5
Note the method I used to create the buffer in nodejs, especially (also tested and verified with -1, but I left the code off for brevity).
Thanks for the replies.
I put the same question over here:Unity Questions
Somebody give me the answer to use:
readFloat: function (offset, data) {
return data.readFloatLE(offset);
},
instead creating a new buffer.
Parameter is a buffer. This was working for me. I still don`t understand why my example is not working.
The following code is a work-in-progress that I am also taking time with to try and learn some more about converting between bits, hex, and Int;
A lot of this is obviously repetitive operations since we're doing the same thing to 7 different "packages," so feel free to gloss over the repeats (just wanted to have entire code structure up to maybe answer some questions ahead of time).
/* Pack bits into containers to send them as 32-bit (4 bytes) items */
int finalBitPackage_1 = 0;
int finalBitPackage_2 = 0;
int finalBitPackage_3 = 0;
int finalBitPackage_4 = 0;
int finalBitPackage_5 = 0;
int finalBitPackage_6 = 0;
int finalBitPackage_7 = 0;
var bitContainer_1 = new BitArray(32, false);
var bitContainer_2 = new BitArray(32, false);
var bitContainer_3 = new BitArray(32, false);
var bitContainer_4 = new BitArray(32, false);
var bitContainer_5 = new BitArray(32, false);
var bitContainer_6 = new BitArray(32, false);
var bitContainer_7 = new BitArray(32, false);
string hexValue = String.Empty;
...
*assign 32 bits (from bools) to every bitContainer[] here*
...
/* Using this single 1-D array for all assignments works because as soon as we convert arrays,
we store the result; this way we never overwrite ourselves */
int[] data = new int[1];
/* Copy containers to a 1-dimensional array, then into an Int for transmission */
bitContainer_1.CopyTo(data, 0);
hexValue = data[0].ToString("X");
finalBitPackage_1 = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
bitContainer_2.CopyTo(data, 0);
hexValue = data[0].ToString("X");
finalBitPackage_2 = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
bitContainer_3.CopyTo(data, 0);
hexValue = data[0].ToString("X");
finalBitPackage_3 = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
bitContainer_4.CopyTo(data, 0);
hexValue = data[0].ToString("X");
finalBitPackage_4 = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
bitContainer_5.CopyTo(data, 0);
hexValue = data[0].ToString("X");
finalBitPackage_5 = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
bitContainer_6.CopyTo(data, 0);
hexValue = data[0].ToString("X");
finalBitPackage_6 = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
bitContainer_7.CopyTo(data, 0);
hexValue = data[0].ToString("X");
finalBitPackage_7 = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
From what I've learned so far, if a binary value is being converted to Int32, the first digit tells if it will be -/+, where 1 indicates (-) and 0 indicates (+); however, in my bitArrays that start with a 0, they show up as a negative number when I do the CopyTo(int[]) transaction, and the bitArrays that start with a 1 show up as a positive when they are copied.
In addition, there is the problem of converting them from their Int32 values into Hex values. Any values that come out of the array conversion as negative don't get the 8 F's added to the front as when checked by http://www.binaryhexconverter.com/, so I wasn't sure the difference in that since my Hex knowledge is limited and I didn't want to lose meaningful data when I transmit the data to another system (over TCP/IP if it matters to anyone). I'll post the values I'm getting out of everything below to help clear it up some.
Variable Binary Int32[] My Hex
bitContainer_1 "01010101010101010101010101010101" "-1431655766" AAAAAAAA
bitContainer_2 "10101010101010101010101010101010" "1431655765" 55555555
bitContainer_3 "00110011001100110011001100110011" "-858993460" CCCCCCCC
bitContainer_4 "11001100110011001100110011001100" "858993459" 33333333
bitContainer_5 "11100011100011100011100011100011" "-954437177" C71C71C7
bitContainer_6 "00011100011100011100011100011100" "954437176" 38E38E38
bitContainer_7 "11110000111100001111000011110000" "252645135" F0F0F0F
Online Hex Values:
FFFFFFFFAAAAAAAA
555555555
FFFFFFFFCCCCCCCC
33333333
FFFFFFFFC71C71C7
38E38E38
F0F0F0F
If every integer sign value is reversed place a -1*theIntegerValue to un-reverse it. It could also have something to do with when you're calling toStirng("X"), maybe use a blank string?
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;
byte checksum;
byte[] toBuff = new byte[20];
toBuff = BitConverter.GetBytes(intNumBuffer);
Array.Reverse(mybyte);
checksum = ComputeChecksum(toBuff); //int to byte array
// At this point, the array is something like this
// toBuff[0] = 25
// toBuff[1] = 0
// toBuff[2] = 0
// toBuff[3] = 0
toBuff[4] = checksum; //HERE IS WHERE OUR OF BOUNDS OCCURS
I am new and would greatly appreciate any help.
Thanks
toBuff = BitConverter.GetBytes(intNumBuffer);
The call to BitConverter.GetBytes() returns a byte array of length 4, because intNumBuffer is an int, which has size 4.
So, that means that the valid indices of toBuff are 0, 1, 2 and 3. Hence the error when you use index 4.
Now, I suppose that you imagined that when you wrote:
byte[] toBuff = new byte[20];
that toBuff would have length 20. Well, it does at this point. But when you subsequently overwrite toBuff, then you have a new and different array.
Probably what you need to do is as follows:
byte[] toBuff = new byte[20];
Array.Copy(BitConverter.GetBytes(intNumBuffer), toBuff, sizeof(int));
Or perhaps:
byte[] toBuff = new byte[20];
byte[] intBytes = BitConverter.GetBytes(intNumBuffer);
Array.Copy(intBytes, toBuff, intBytes.Length);
Either of these will copy the bits returned by the call to GetBytes() into toBuff.
This is normal, because you only add an item in the range of 0 to 3.
You could check first if the toBuff[someIndex] actually has a value and thus is not null.
BitCOnverter.GetBytes return an array of 4 check :http://msdn.microsoft.com/en-us/library/de8fssa4(v=vs.110).aspx
toBuff = BitConverter.GetBytes(intNumBuffer);
I am honestly really confused on reading binary files in C#.
I have C++ code for reading binary files:
FILE *pFile = fopen(filename, "rb");
uint n = 1024;
uint readC = 0;
do {
short* pChunk = new short[n];
readC = fread(pChunk, sizeof (short), n, pFile);
} while (readC > 0);
and it reads the following data:
-156, -154, -116, -69, -42, -36, -42, -41, -89, -178, -243, -276, -306,...
I tried convert this code to C# but cannot read such data. Here is code:
using (var reader = new BinaryReader(File.Open(filename, FileMode.Open)))
{
sbyte[] buffer = new sbyte[1024];
for (int i = 0; i < 1024; i++)
{
buffer[i] = reader.ReadSByte();
}
}
and i get the following data:
100, -1, 102, -1, -116, -1, -69, -1, -42, -1, -36
How can i get similar data?
A short is not a signed byte, it's a signed 16 bit value.
short[] buffer = new short[1024];
for (int i = 0; i < 1024; i++) {
buffer[i] = reader.ReadInt16();
}
That's because in C++ you're reading shorts and in C# you're reading signed bytes (that's why SByte means). You should use reader.ReadInt16()
Your C++ code reads 2 bytes at a time (you're using sizeof(short)), while your C# code reads one byte at a time. A SByte (see http://msdn.microsoft.com/en-us/library/d86he86x(v=vs.71).aspx) uses 8 bits of storage.
You should use the same data type to get the correct output or cast to a new type.
In c++ you are using short. (i suppose the file is also written with short) so use short itself in c#. or you can use Sytem.Int16.
You are getting different values because short and sbyte are not equivalent. short is 2 bytes and Sbyte is 1 byte
using (var reader = new BinaryReader(File.Open(filename, FileMode.Open)))
{
System.Int16[] buffer = new System.Int16[1024];
for (int i = 0; i < 1024; i++)
{
buffer[i] = reader.ReadInt16();
}
}