I'm converting a long to a 8 slot byte array with C#
Byte[] Data = BitConverter.GetBytes(data.LongLength);
For example if data.LongLenght is 172085, I get the following array { 53,160,2,0,0,0,0,0 }
But then after I send this to my c++ server I would like to get it to a long again.
I tryed this but without success...
long fileLenght = 0;
for( int i=0;i < 8; ++i)
fileLenght = (fileLenght << 8) + Data[i];
Whenever you send data across a network you have to mind endianness
In your case, it looks like the proper way to recreate the long from the byte array would be to reconstruct it from right to left:
long fileLength = 0;
for( int i=7; i >= 0; i--)
fileLength = (fileLength << 8) + Data[i];
But this will not always be the case. Depending on the hardware and operating system at the end points, and the network transfer protocols you use you may have data coming in big-endian or little-endian format, and the receiving end may be little-endian or big-endian.
From the documentation:
The order of bytes in the array returned by the GetBytes method depends on whether the computer architecture is little-endian or big-endian.
It looks like on your hardware the array is sent with its least significant bytes first. Therefore, you should start your loop from the end of the array:
int64_t fileLenth = 0;
for( int i=7;i >= 0; --i)
fileLenght = (fileLenght << 8) + Data[i];
Demo. (prints 172085)
In order to achieve better compatibility with C# you should use a system-independent 64-bit integral type instead of long, i.e. int64_t.
If both ends have the same byte order (C# is always little-endian, probably your C++ is also):
long long fileLength;
memcpy(&fileLength, Data, 8);
The optimizing compiler will almost certainly turn that into a single 64-bit move, so don't worry that it looks like an expensive function call.
Related
What is fastest way to write int[] array to byte[] array, but only LSB (last 8 bits)? I used for loop and bitmask bArray[i] = (byte)(iArray[i] & 0xFF), but array is very long (+900k) and this take about 50ms. Do you know maybe other faster option?
You can try parallelizing the workload:
Parallel.For(0,iArray.Length, i => bArray[i] = (byte)(iArray[i] & 0xFF));
This will spawn multiple threads to do the conversion. It tends to be faster on my machine, but, will sometimes take longer due to the overhead of spawning multiple threads.
What are you doing that 50ms is too slow?
Part of the slowness comes from the need to read more data than you need: when you do
array[i] & 0xFF
you read the entire four bytes of an int, only to drop three most significant ones.
You could avoid this overhead with unsafe code. Keep in mind that the approach below assumes little endian architecture:
static unsafe void CopyLsbUnsafe(int[] from, byte[] to) {
fixed (int* s = from) {
fixed (byte* d = to) {
byte* sb = (byte*) s;
int* db = (int*)d;
int* end = db + to.Length/4;
while (db != end) {
*db++ = (*(sb + 0) << 0)
| (*(sb + 4) << 8)
| (*(sb + 8) << 16)
| (*(sb + 12) << 24);
sb += 16;
}
}
}
}
The above code re-interprets the int array as an array of bytes, and the array of bytes as an array of integers. Then it reads every 4-th byte into the destination array using a pointer, writing to the destination in groups of four bytes using an integer assignment.
My testing shows a respectable 60% improvement over a simple loop.
I need to combine two Bytes into one int value.
I receive from my camera a 16bit Image were two successive bytes have the intensity value of one pixel. My goal is to combine these two bytes into one "int" vale.
I manage to do this using the following code:
for (int i = 0; i < VectorLength * 2; i = i + 2)
{
NewImageVector[ImagePointer] = ((int)(buffer.Array[i + 1]) << 8) | ((int)(buffer.Array[i]));
ImagePointer++;
}
My image is 1280*960 so VectorLength==1228800 and the incomming buffer size is 2*1228800=2457600 elements...
Is there any way that I can speed this up?
Maybe there is another way so I don't need to use a for-loop.
Thank you
You could use the equivalent to the union of c. Im not sure if faster, but more elegant:
[StructLayout(LayoutKind.Explicit)]
struct byte_array
{
[FieldOffset(0)]
public byte byte1;
[FieldOffset(1)]
public byte byte2;
[FieldOffset(0)]
public short int0;
}
use it like this:
byte_array ba = new byte_array();
//insert the two bytes
ba.byte1 = (byte)(buffer.Array[i]);
ba.byte2 = (byte)(buffer.Array[i + 1]);
//get the integer
NewImageVector[ImagePointer] = ba.int1;
You can fill your two bytes and use the int. To find the faster way take the StopWatch-Class and compare the two ways like this:
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
//The code
stopWatch.Stop();
MessageBox.Show(stopWatch.ElapsedTicks.ToString()); //Or milliseconds ,...
Assuming you can (re-)define NewImageVector as a short[], and every two consecutive bytes in Buffer should be transformed into a short (which basically what you're doing now, only you cast to an int afterwards), you can use Buffer.BlockCopy to do it for you.
As the documentation tells, you Buffer.BlockCopy copies bytes from one array to another, so in order to copy your bytes in buffer you need to do the following:
Buffer.BlockCopy(Buffer, 0, NewImageVector, 0, [NumberOfExpectedShorts] * 2)
This tells BlockCopy that you want to start copying bytes from Buffer, starting at index 0, to NewImageVector starting at index 0, and you want to copy [NumberOfExpectedShorts] * 2 bytes (since every short is two bytes long).
No loops, but it does depend on the ability of using a short[] array instead of an int[] array (and indeed, on using an array to begin with).
Note that this also requires the bytes in Buffer to be in little-endian order (i.e. Buffer[index] contains the low byte, buffer[index + 1] the high byte).
You can achieve a small performance increase by using unsafe pointers to iterate the arrays. The following code assumes that source is the input byte array (buffer.Array in your case). It also assumes that source has an even number of elements. In production code you would obviously have to check these things.
int[] output = new int[source.Length / 2];
fixed (byte* pSource = source)
fixed (int* pDestination = output)
{
byte* sourceIterator = pSource;
int* destIterator = pDestination;
for (int i = 0; i < output.Length; i++)
{
(*destIterator) = ((*sourceIterator) | (*(sourceIterator + 1) << 8));
destIterator++;
sourceIterator += 2;
}
}
return output;
I'm trying to debug some bit shifting operations and I need to visualize the bits as they exist before and after a Bit-Shifting operation.
I read from this answer that I may need to handle backfill from the shifting, but I'm not sure what that means.
I think that by asking this question (how do I print the bits in a int) I can figure out what the backfill is, and perhaps some other questions I have.
Here is my sample code so far.
static string GetBits(int num)
{
StringBuilder sb = new StringBuilder();
uint bits = (uint)num;
while (bits!=0)
{
bits >>= 1;
isBitSet = // somehow do an | operation on the first bit.
// I'm unsure if it's possible to handle different data types here
// or if unsafe code and a PTR is needed
if (isBitSet)
sb.Append("1");
else
sb.Append("0");
}
}
Convert.ToString(56,2).PadLeft(8,'0') returns "00111000"
This is for a byte, works for int also, just increase the numbers
To test if the last bit is set you could use:
isBitSet = ((bits & 1) == 1);
But you should do so before shifting right (not after), otherwise you's missing the first bit:
isBitSet = ((bits & 1) == 1);
bits = bits >> 1;
But a better option would be to use the static methods of the BitConverter class to get the actual bytes used to represent the number in memory into a byte array. The advantage (or disadvantage depending on your needs) of this method is that this reflects the endianness of the machine running the code.
byte[] bytes = BitConverter.GetBytes(num);
int bitPos = 0;
while(bitPos < 8 * bytes.Length)
{
int byteIndex = bitPos / 8;
int offset = bitPos % 8;
bool isSet = (bytes[byteIndex] & (1 << offset)) != 0;
// isSet = [True] if the bit at bitPos is set, false otherwise
bitPos++;
}
I'm currently trying to get this C code converted into C#.
Since I'm not really familiar with C I'd really apprecheate your help!
static unsigned char byte_table[2080] = {0};
First of, some bytearray gets declared but never filled which I'm okay with
BYTE* packet = //bytes come in here from a file
int unknownVal = 0;
int unknown_field0 = *(DWORD *)(packet + 0x08);
do
{
*((BYTE *)packet + i) ^= byte_table[(i + unknownVal) & 0x7FF];
++i;
}
while (i <= packet[0]);
But down here.. I really have no idea how to translate this into C#
BYTE = byte[] right?
DWORD = double?
but how can (packet + 0x08) be translated? How can I add a hex to a bytearray? Oo
I'd be happy about anything that helps! :)
In C, setting any set of memory to {0} will set the entire memory area to zeroes, if I'm not mistaken.
That bottom loop can be rewritten in a simpler, C# friendly fashion.
byte[] packet = arrayofcharsfromfile;
int field = packet[8]+(packet[9]<<8)+(packet[10]<<16)+(packet[11]<<24); //Assuming 32 bit little endian integer
int unknownval = 0;
int i = 0;
do //Why waste the newline? I don't know. Conventions are silly!
{
packet[i] ^= byte_table[(i+unknownval) & 0x7FF];
} while( ++i <= packet[0] );
field is set by taking the four bytes including and following index 8 and generating a 32 bit int from them.
In C, you can cast pointers to other types, as is done in your provided snippet. What they're doing is taking an array of bytes (each one 1/4 the size of a DWORD) and adding 8 to the index which advances the pointer by 8 bytes (since each element is a byte wide) and then treating that pointer as a DWORD pointer. In simpler terms, they're turning the byte array in to a DWORD array, and then taking index 2, as 8/4=2.
You can simulate this behavior in a safe fashion by stringing the bytes together with bitshifting and addition, as I demonstrated above. It's not as efficient and isn't as pretty, but it accomplishes the same thing, and in a platform agnostic way too. Not all platforms are little endian.
I'm moving a java android app to windows metro, this app has a heavy use of blobs and decoding (the blobs are coded to take less space on the DB
After copying the entire decoding code, the result is slightly different.
There are some parts where the asks if the byte value is lower than 0, as I understand, bytes on c# are alaways unsigned so i don't understand why the result is not the same as the android app.
Here is a snippet.
for (int i = 0; i < length; i++) {
s[six] = (byte) (blob[i] ^ pronpassword[ix]); //pronpass is a string password
if (s[six] == 0) {
s[six + 1] = (byte)'-';
s[six] ^= 128;
s[six] = (byte) PRON_MAP[(byte) s[six]];
six++;
} else {
s[six] = (byte) PRON_MAP[(byte) s[six]];
}
six++;
ix++;
if (ix == plen)
ix = 0;
}
Thanks!
In Java, byte is signed. There is actually no such thing as an unsigned byte in Java. It's equivalent to C#'s sbyte, so that's the type you should port it to.