Adding byte[] interpreted as a number and short - c#

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);

Related

byte array from specific index as struct in c# without making a copy

Currently I code client-server junk and deal a lot with C++ structs passed over network.
I know about ways provided here Reading a C/C++ data structure in C# from a byte array, but they all about making a copy.
I want to have something like that:
struct/*or class*/ SomeStruct
{
public uint F1;
public uint F2;
public uint F3;
}
Later in my code I want to have something like that:
byte[] Data; //16 bytes that I got from network
SomeStruct PartOfDataAsSomeStruct { get { return /*make SomeStruct instance based on this.Data starting from index 4, without copying it. So when I do PartOfDataAsSomeStruct.F1 = 132465; it also changes bytes 4, 5, 6 and 7 in this.Data.*/; } }
If this is possible, please, tell how?
Like so?
byte[] data = new byte[16];
// 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
Console.WriteLine(BitConverter.ToString(data));
ref SomeStruct typed = ref Unsafe.As<byte, SomeStruct>(ref data[4]);
typed.F1 = 42;
typed.F2 = 3;
typed.F3 = 9;
// 00-00-00-00-2A-00-00-00-03-00-00-00-09-00-00-00
Console.WriteLine(BitConverter.ToString(data));
This coerces the data from the middle of the byte-array using a ref-local that is an "interior managed pointer" to the data. Zero copies.
If you need multiple items (like how a vector would work), you can do the same thing with spans and MemoryMarshal.Cast
Note that it uses CPU-endian rules for the elements - little endian in my case.
For spans:
byte[] data = new byte[256];
// create a span of some of it
var span = new Span<byte>(data, 4, 128);
// now coerce the span
var typed = MemoryMarshal.Cast<byte, SomeStruct>(span);
Console.WriteLine(typed.Length); // 10 of them fit
typed[3].F1 = 3; // etc
Thank you for the correction, Marc Gravell. And thank you for the example.
Here is a way using Class and Bitwise Operators, without pointers, to do the samething:
class SomeClass
{
public byte[] Data;
public SomeClass()
{
Data = new byte[16];
}
public uint F1
{
get
{
uint ret = (uint)(Data[4] << 24 | Data[5] << 16 | Data[6] << 8 | Data[7]);
return ret;
}
set
{
Data[4] = (byte)(value >> 24);
Data[5] = (byte)(value >> 16);
Data[6] = (byte)(value >> 8);
Data[7] = (byte)value;
}
}
}
Testing:
SomeClass sc = new SomeClass();
sc.F1 = 0b_00000001_00000010_00000011_00000100;
Console.WriteLine(sc.Data[3].ToString() + " " + sc.Data[4].ToString() + " " + sc.Data[5].ToString() + " " + sc.Data[6].ToString());
Console.WriteLine(sc.F1.ToString());
//Output:
//1 2 3 4
//16909060

C# Bitwise XOR two very large hex numbers

I have two hex numbers, which, for the purposes of experimenting with OTP, I'm trying to XOR with C#. Unfortunately, both numbers are on the order of hundreds of digits - clearly far too large to store in an int or long. How do I store/XOR them? Right now, I'm storing as BigIntegers like so:
public static string XOR(string string_1, string string_2){
BigInteger b1 = BigInteger.Parse(string_1, System.Globalization.NumberStyles.AllowHexSpecifier);
BigInteger b2 = BigInteger.Parse(string_2, System.Globalization.NumberStyles.AllowHexSpecifier);
BigInteger retVal = b1 ^ b2;
return retVal.ToString("X");
}
which isn't producing the expected result. Thanks!
EDIT:
Input:
string_1 = 32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd90f1fa6ea5ba47b01c909ba7696cf606ef40c04afe1ac0aa8148dd066592ded9f8774b529c7ea125d298e8883f5e9305f4b44f915cb2bd05af51373fd9b4af511039fa2d96f83414aaaf261bda2e97b170fb5cce2a53e675c154c0d9681596934777e2275b381ce2e40582afe67650b13e72287ff2270abcf73bb028932836fbdecfecee0a3b894473c1bbeb6b4913a536ce4f9b13f1efff71ea313c8661dd9a4ce
string_2 = 71946f9bbb2aeadec111841a81abc300ecaa01bd8069d5cc91005e9fe4aad6e04d513e96d99de2569bc5e50eeeca709b50a8a987f4264edb6896fb537d0a716132ddc938fb0f836480e06ed0fcd6e9759f40462f9cf57f4564186a2c1778f1543efa270bda5e933421cbe88a4a52222190f471e9bd15f652b653b7071aec59a2705081ffe72651d08f822c9ed6d76e48b63ab15d0208573a7eef027
Expected result (according to Python and this online XOR calculator):
32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd90f1fa6ea5b83624730b208d83b237176b5a41e13d1a2c0080f55d6fb05e4fd9a6e8aff84a9eec74ec0e3115dd0808c011baa15b2c29edad06d6c319976fc7c7eb6a8727e79906c96397dd14594a17511e2ba018c3267935877b5c2c1750f28b2d5bf55faa6c2218c30e58f17542717ad6f8622dd0069a4886d20d3d657a80a869c8f6025399f914f23e5ccd3a999c271a50994c7db959c5c0b73334d15ba3754e9
Seems somebody doesn't want to believe.
var string_1 = "32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd90f1fa6ea5ba47b01c909ba7696cf606ef40c04afe1ac0aa8148dd066592ded9f8774b529c7ea125d298e8883f5e9305f4b44f915cb2bd05af51373fd9b4af511039fa2d96f83414aaaf261bda2e97b170fb5cce2a53e675c154c0d9681596934777e2275b381ce2e40582afe67650b13e72287ff2270abcf73bb028932836fbdecfecee0a3b894473c1bbeb6b4913a536ce4f9b13f1efff71ea313c8661dd9a4ce";
var string_2 = "71946f9bbb2aeadec111841a81abc300ecaa01bd8069d5cc91005e9fe4aad6e04d513e96d99de2569bc5e50eeeca709b50a8a987f4264edb6896fb537d0a716132ddc938fb0f836480e06ed0fcd6e9759f40462f9cf57f4564186a2c1778f1543efa270bda5e933421cbe88a4a52222190f471e9bd15f652b653b7071aec59a2705081ffe72651d08f822c9ed6d76e48b63ab15d0208573a7eef027";
//copied from https://xor.pw/?
string expectedResult = "32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd90f1fa6ea5ba3624730b208d83b237176b5a41e13d1a2c0080f55d6fb05e4fd9a6e8aff84a9eec74ec0e3115dd0808c011baa15b2c29edad06d6c319976fc7c7eb6a8727e79906c96397dd14594a17511e2ba018c3267935877b5c2c1750f28b2d5bf55faa6c2218c30e58f17542717ad6f8622dd0069a4886d20d3d657a80a869c8f6025399f914f23e5ccd3a999c271a50994c7db959c5c0b73334d15ba3754e9";
BigInteger b1 = BigInteger.Parse(string_1, NumberStyles.HexNumber);
BigInteger b2 = BigInteger.Parse(string_2, NumberStyles.HexNumber);
BigInteger retVal = b1 ^ b2;
var res = retVal.ToString("X").ToLower() == expectedResult;
Guess the res in answer. Of course TRUE. :)

Convert byte[] to short[]

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.

hex to float conversion

I have a 4 byte hex number:
08fdc941
it should be convrted to a float number: 25.25, but I don't know how? I use C#
what is the correct way of converting from hex to float?
From this page on MSDN "How to: Convert Between Hexadecimal Strings and Numeric Types (C# Programming Guide)".
string hexString = "43480170";
uint num = uint.Parse(hexString, System.Globalization.NumberStyles.AllowHexSpecifier);
byte[] floatVals = BitConverter.GetBytes(num);
float f = BitConverter.ToSingle(floatVals, 0);
Console.WriteLine("float convert = {0}", f);
// Output: 200.0056
Something like this:
byte[] bytes = BitConverter.GetBytes(0x08fdc941);
if (BitConverter.IsLittleEndian)
{
bytes = bytes.Reverse().ToArray();
}
float myFloat = BitConverter.ToSingle(bytes, 0);
This yields 25.24855, which is what I think you were looking for.
var bytes = BitConverter.GetBytes(0x08fdc941);
Array.Reverse(bytes);
var result = BitConverter.ToSingle(bytes, 0);
Are you sure it's the right way around, since BitConverter.ToSingle(BitConverter.GetBytes(0x08fdc941).Reverse().ToArray(), 0) is close.
Edit:
Incidentally, http://en.wikipedia.org/wiki/Single_precision_floating-point_format gives a pretty good summary of how ISO/IEC/IEEE 60559 (IEEE 754) single-precision floating-point numbers work.
string hexString = 08fdc941;
Int32 IntRep = Int32.Parse(hexString, NumberStyles.AllowHexSpecifier);
// Integer to Byte[] and presenting it for float conversion
float myFloat = BitConverter.ToSingle(BitConverter.GetBytes(IntRep), 0);
// There you go
return myFloat;
For more information, see this:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/how-to-convert-between-hexadecimal-strings-and-numeric-types

Converting 2 bytes to Short in C#

I'm trying to convert two bytes into an unsigned short so I can retrieve the actual server port value. I'm basing it off from this protocol specification under Reply Format. I tried using BitConverter.ToUint16() for this, but the problem is, it doesn't seem to throw the expected value. See below for a sample implementation:
int bytesRead = 0;
while (bytesRead < ms.Length)
{
int first = ms.ReadByte() & 0xFF;
int second = ms.ReadByte() & 0xFF;
int third = ms.ReadByte() & 0xFF;
int fourth = ms.ReadByte() & 0xFF;
int port1 = ms.ReadByte();
int port2 = ms.ReadByte();
int actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port1 , (byte)port2 }, 0);
string ip = String.Format("{0}.{1}.{2}.{3}:{4}-{5} = {6}", first, second, third, fourth, port1, port2, actualPort);
Debug.WriteLine(ip);
bytesRead += 6;
}
Given one sample data, let's say for the two byte values, I have 105 & 135, the expected port value after conversion should be 27015, but instead I get a value of 34665 using BitConverter.
Am I doing it the wrong way?
If you reverse the values in the BitConverter call, you should get the expected result:
int actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port2 , (byte)port1 }, 0);
On a little-endian architecture, the low order byte needs to be second in the array. And as lasseespeholt points out in the comments, you would need to reverse the order on a big-endian architecture. That could be checked with the BitConverter.IsLittleEndian property. Or it might be a better solution overall to use IPAddress.HostToNetworkOrder (convert the value first and then call that method to put the bytes in the correct order regardless of the endianness).
BitConverter is doing the right thing, you just have low-byte and high-byte mixed up - you can verify using a bitshift manually:
byte port1 = 105;
byte port2 = 135;
ushort value = BitConverter.ToUInt16(new byte[2] { (byte)port1, (byte)port2 }, 0);
ushort value2 = (ushort)(port1 + (port2 << 8)); //same output
To work on both little and big endian architectures, you must do something like:
if (BitConverter.IsLittleEndian)
actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port2 , (byte)port1 }, 0);
else
actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port1 , (byte)port2 }, 0);

Categories

Resources