Appending Array on top of Array to specified length - c#

I've made a function to append an array on top of itself to a specified length. The only issue I'm having is when the array is an odd number, say 9, and the length I'm trying to get it to, for example 20, it would output with 2 zeros at the end. I'm sure there's a way to have the array fill in every byte.
Current Function:
public static byte[] AppendToLen(byte[] input, int length)
{
byte[] output = new byte[length];
if (length <= input.Length) return null;
for (int i = 0; i < length / input.Length; i++)
Array.Copy(input, 0, output, input.Length * i, input.Length);
return output;
}
Block of bytes
byte[] Block = new byte[0x10] { 0x02, 0x03, 0xFF, 0x04, 0x61, 0x37, 0x5f, 0xe8, 0x19, 0x70, 0xa2, 0x77, 0x8c, 0x94, 0x89, 0xb4 };
An example is:
foreach(byte bit in AppendToLen(Block, 56)) {
Console.WriteLine(bit.ToString("X2"));
}
Ouput: 0203FF0461375FE81970A2778C9489B40203FF0461375FE81970A2778C9489B40203FF0461375FE81970A2778C9489B40000000000000000

In the example above you are only iterating twice because the length / input.Length term rounds down to 2. Remember that this is integer division. Also, remember not to walk off the end of your array. The snippet below does what you want.
public static byte[] AppendToLen(byte[] input, int length)
{
byte[] output = new byte[length];
if (length <= input.Length) return null;
// Just use offset here since that's what you care about
for (int offset = 0; offset < length; offset += input.Length)
// Copy as much of the input array as possible to the output,
// starting at this iteration's offset
Array.Copy(input, 0, output, offset, Math.Min(length - offset, input.Length));
return output;
}

The problem is that you are not assigning any value to the remainder bytes. In your example 56 % 16 = 8, so you have 8 bytes left at the end after your loop without initialize. Now, the way you want to fill those I don't know, maybe with the first 8 bytes in your input array. If so, you would need to add an extra check after the loop to see if the remainder is > 0, and copy those 8 (remainder) bytes to the last positions of your array.

Related

add variable to hex stream

in c# i want to add variable from trackbar.value to hex stream:
UdpClient udpClient = new UdpClient("192.168.1.205", 52381);=
Byte[] sendBytes = new byte[] {
0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0x81, 0x01,
0x04, 0x07, 0x0("trackbar.value"), 0xFF
};
try
{
udpClient.Send(sendBytes, sendBytes.Length);
}
catch (Exception)
{
Console.WriteLine(e.ToString());
}
ho do i syntax that?
If you have a fixed size byte array you can do this:
Byte[] sendBytes = new byte[] {
0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0x81, 0x01,
0x04, 0x07, 0x00, 0xFF
};
sendBytes[12] = (byte) trackbar.value;
BUT: This will of course lead to data loss if your trackbar.value is not a byte value and exceeds a maximum value of 255.
So you will either have to reduce precision and scale your value, something like this:
byte scaledValue = (byte) ((double) trackbar.value / [maximum_trackbar_value] * 255.0);
or increase the amount of bytes used in your message to transfer the value.
For example using a 16bit integer with a maximum value of 65535 (= 2^16 - 1) will require 2 bytes. To "split" your value into these 2 bytes you will have to do a bit shift like this
1. sendBytes[12] = (byte) trackbar.value;
2. sendBytes[13] = (byte) (trackbar.value >> 8);
The second line will shift the highest 8 bits of the value to the right so they can be put into the next byte, which can only be used for 8 bits, the rest will be cut off. For better understanding:
1. (byte) (00000101 00111001) = 00111001
2. (byte) ((00000101 00111001) >> 8) = (byte) (00000000 00000101) = 00000101
This will transfer your value in little endian order, meaning the less significant byte ("smaller value") first in your array. You will find more details on that topic here: https://en.wikipedia.org/wiki/Endianness. The receiver of your message will have to do the reverse:
int trackbarValue = (receivedBytes[12] & 0xFF) | ((receivedBytes[13] & 0xFF) << 8);
Here are two functions to make this a little more general:
public static byte[] GetBytesLittleEndian(int num, int byteCount)
{
var result = new byte[byteCount];
for (int i = 0; i < byteCount; i++)
{
result[i] = (byte)(num >> (i * 8));
}
return result;
}
public static int ParseLittleEndian(byte[] data, int byteCount)
{
int parsed = 0;
for (int i = 0; i < byteCount; i++)
{
parsed |= data[i] << (i * 8);
}
return parsed;
}
Of course there is build-in functionality for that, see BitConverter.GetBytes() for example, but I think it won't hurt to know some details ;)

Equivalent C code in C#. (uint8_t *) cast?

I am trying to convert these C piece of code into C#. But I've stumble in some parts that I don't understand exactly what is happening, so I am unable to translate it.
void foo(uint64_t *output, uint64_t *input, uint32_t Length){
uint64_t st[25];
memcpy(st, input, Length);
((uint8_t *)st)[Length] = 0x01;
memset(((uint8_t *)st) + Length + 1, 0x00, 128 - Length - 1);
for(int i = 16; i < 25; ++i) st[i] = 0x00UL;
// Last bit of padding
st[16] = 0x8000000000000000UL;
bar(st);
memcpy(output, st, 200);
}
More specifically in the ((uint8_t *)st)[Length] = 0x01; part. I cannot understand the cast/pointer in this line. Why is the * there for? If somebody could explain what is happening, I would be grateful.
What I got so far in C#:
private void foo(ref ulong[] output, ref ulong[] input, uint Length)
{
ulong[] st = new ulong[25];
//memcpy(st, input, Length);
Buffer.BlockCopy(input, 0, st, 0, (int)Length);
// Help in these line please:
//((uint8_t *)st)[Length] = 0x01;
// Still don't know what to do here too:
//memset(((byte)st) + Length + 1, 0x00, 128 - Length - 1);
for (int i = 16; i < 25; ++i)
{
st[i] = 0x00U;
}
// Last bit of padding
st[16] = 0x8000000000000000U;
bar(st);
//memcpy(output, st, 200);
Buffer.BlockCopy(st, 0, output, 0, 200);
}
Thank you.
What your function does is rather primitive memory manipulation:
void foo(uint64_t *output, uint64_t *input, uint32_t Length)
{
uint64_t st[25];
Your function takes a pointer to 16 elements of uint64_t and prepares a local buffer (st) to store a copy of them.
memcpy(st, input, Length);
((uint8_t *)st)[Length] = 0x01;
memset(((uint8_t *)st) + Length + 1, 0x00, 128 - Length - 1);
Make a copy of the input array into st but insert a byte with value 1 at an offset of Length bytes from the start.
for(int i = 16; i < 25; ++i) st[i] = 0x00UL;
The remaining 8 elements of the buffer are cleared to 0. Writing st[16] is pointless as it will be changed again by the next line...
// Last bit of padding
st[16] = 0x8000000000000000UL;
Now we have 16*8 bytes from the input buffer, 1 extra byte with value 1 inserted somewhere and the remaining elements are filled with 1<<63 and lots of 0 bytes.
bar(st);
memcpy(output, st, 200);
}
Do something we have no clue about and copy the resulting 25 elements into the output buffer

Replacing bits in a Byte Array C#

I want to open a Bitmap File in C# as an array of bytes, and replace certain bytes within that array, and rewrite the Byte array back to disk as a bitmap again.
My current approach is to read into a byte[] array, then convert that array to a list to begin editing individual bytes.
originalBytes = File.ReadAllBytes(path);
List<byte> listBytes = new List<Byte>(originalBytes);
How does one go about replacing every nth byte in the array with a user configured/different byte each time and rewriting back to file?
no need in List<byte>
replaces every n-th byte with customByte
var n = 5;
byte customByte = 0xFF;
var bytes = File.ReadAllBytes(path);
for (var i = 0; i < bytes.Length; i++)
{
if (i%n == 0)
{
bytes[i] = customByte;
}
}
File.WriteAllBytes(path, bytes);
Assuming that you want to replace every nth byte with the same new byte, you could do something like this (shown for every 3rd byte):
int n = 3;
byte newValue = 0xFF;
for (int i = n; i < listBytes.Count; i += n)
{
listBytes[i] = newValue;
}
File.WriteAllBytes(path, listBytes.ToArray());
Of course, you could also do this with a fancy LINQ expression which would be harder to read i guess.
Technically, you can implement something like this:
// ReadAllBytes returns byte[] array, we have no need in List<byte>
byte[] data = File.ReadAllBytes(path);
// starting from 0 - int i = 0 - will ruin BMP header which we must spare
// if n is small, you may want to start from 2 * n, 3 * n etc.
// or from some fixed offset
for (int i = n; i < data.Length; i += n)
data[i] = yourValue;
File.WriteAllBytes(path, data);
Please notice, that Bitmap file has a header
https://en.wikipedia.org/wiki/BMP_file_format
that's why I've started loop from n, not from 0

Convert ushort[] into byte[] and back

I have a ushort array that needs converting into a byte array to be transferred over a network.
Once it gets to its destination, I need then reconvert it back into the same ushort array it was to being with.
Ushort Array
Is an array that is of Length 217,088 (1D array of broken down image 512 by 424). It's stored as 16-bit unsigned integers. Each element is 2 bytes.
Byte Array
It needs to be converted into a byte array for network purposes. As each ushort element is worth 2 bytes, I assume the byte array Length needs to be 217,088 * 2?
In terms of converting, and then 'unconverting' correctly, I am unsure on how to do that.
This is for a Unity3D project that is in C#. Could someone point me in the right direction?
Thanks.
You're looking for BlockCopy:
https://msdn.microsoft.com/en-us/library/system.buffer.blockcopy(v=vs.110).aspx
and yes, short as well as ushort is 2 bytes long; and that's why corresponding byte array should be two times longer than initial short one.
Direct (byte to short):
byte[] source = new byte[] { 5, 6 };
short[] target = new short[source.Length / 2];
Buffer.BlockCopy(source, 0, target, 0, source.Length);
Reverse:
short[] source = new short[] {7, 8};
byte[] target = new byte[source.Length * 2];
Buffer.BlockCopy(source, 0, target, 0, source.Length * 2);
using offsets (the second and the fourth parameters of Buffer.BlockCopy) you can have 1D array being broken down (as you've put it):
// it's unclear for me what is the "broken down 1d array", so
// let it be an array of array (say 512 lines, each of 424 items)
ushort[][] image = ...;
// data - sum up all the lengths (512 * 424) and * 2 (bytes)
byte[] data = new byte[image.Sum(line => line.Length) * 2];
int offset = 0;
for (int i = 0; i < image.Length; ++i) {
int count = image[i].Length * 2;
Buffer.BlockCopy(image[i], offset, data, offset, count);
offset += count;
}

Converting Type Int to Type Byte

I have a small set of code that attempts to bit-shift a 1-bit from the 0 index to the 7 index in a byte. After each bit shift I want to take the int value and convert it to a byte:
for(int t=0; t<8; t++)
{
int ShiftBit = 0x80 >> t;
byte ShiftBitByte = Convert.ToByte(ShiftBit.ToString(),8);
}
I would expect the outputs to be:
0x80
0x40
0x20
0x10
0x08
0x04
0x02
0x01
When I run my code I encounter an exception "Additional non-parsable characters are at the end of the string." Is there a better way to capture these bytes?
Thank you
Why don't do you this?
for ( int i = 0 ; i < 8 ; ++i )
{
int s = 0x80 >> i ;
byte b = (byte) s ;
)
Or (cleaner):
for ( int i = 0x00000080 ; i != 0 ; i >>1 )
{
byte b = (byte) i ;
}
To turn a byte into a hex string, something like
byte b = ...
string s = string.Format("0x{0:X2}",b) ;
Ought to do you. But a byte is a number, it doesn't have a format (representation) until you turn it into a string a give it one.
Are you looking for this ?
for (int t = 0; t < 8; t++)
{
int ShiftBit = 0x80 >> t;
byte ShiftBitByte = (byte) ShiftBit;
Console.WriteLine("0x{0:X}",ShiftBitByte);
}
See Standard Numeric Format Strings
You're getting the error because you are erroneously specifying that the string is in base 8. The digit '8' is not a legal digit in base 8, which uses only 0 through 7.
Why not
for (byte b = 0x80; b != 0; b >>= 1)
?
Thanks for catching that ... what I really meant to write was shift a bit in int 0x10000000 from index 0 to 7 and then convert it to a byte each time for an array [0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01]. Is that possible?
I don't understand what int 0x10000000 has to do with it. If you want that array, you can achieve that in any of a number of ways:
byte[] xs = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
byte[] ys = Enumerable.Range(0, 8).Select(i => (byte)(0x80 >> i)).ToArray();
byte[] zs = new byte[8];
for (int index = 0; index < zs.Length; index++)
zs[index] = (byte)(0x80 >> index);

Categories

Resources