in c++:
byte des16[16];
....
byte *d = des16+8;
in c#?
byte des16[16];
[0] 207 'Ï' unsigned char
[1] 216 'Ø' unsigned char
[2] 108 'l' unsigned char
[3] 93 ']' unsigned char
[4] 249 'ù' unsigned char
[5] 249 'ù' unsigned char
[6] 100 'd' unsigned char
[7] 0 unsigned char
[8] 76 'L' unsigned char
[9] 50 '2' unsigned char
[10] 104 'h' unsigned char
[11] 118 'v' unsigned char
[12] 104 'h' unsigned char
[13] 191 '¿' unsigned char
[14] 171 '«' unsigned char
[15] 199 'Ç' unsigned char
after
byte *d = des16+8;
d = "L2hvh¿«Ç†¿æ^ òÎL2hvh¿«Ç"
C# (generally speaking) has no pointers. Maybe the following is what you are after:
byte[] des16 = new byte[16];
byte byteAtIndex8 = des16[8];
This code gives you the element at index 8.
If I read your code correctly, you are trying to get the address of the element at index 8. This is - generally speaking - not possible with C# (unless you use unsafe code).
I think this would be more appropriate (though it depends on how d is used):
byte[] des16 = new byte[16];
IEnumerable<byte> d = des16.Skip(8);
Using pure managed code, you cannot use pointers to locations. Since d takes a pointer to the 8th element of the array, the closest analog would be creating an enumeration of des16 skipping the first 8 items. If you are just iterating through the items, this would be the best choice.
I should also mention that Skip() is one of many extension methods available for arrays (and other IEnumerables) in .Net 3.5 (VS2008/VS2010) and up which I could only assume you were using. You wouldn't be able to use it if you are using .Net 2.0 (VS2003/VS2005).
If d is used to access the offset elements in des16 like an array, it could be converted to an array as well.
byte[] d = des16.Skip(8).ToArray();
Note this creates a separate instance of an array which contains the items in des16 excluding the first 8.
Otherwise it's not completely clear what the best use would be without seeing how it is used.
[edit]
It appears you are working with null-terminated strings in a buffer in .Net 2.0 possibly (if Skip() isn't available). If you want the string representation, you can convert it to a native string object.
byte[] des16 = new byte[16];
char[] chararr = Array.ConvertAll(des16, delegate(byte b) { return (char)b; }); //convert to an array of characters
string str = new String(chararr, 8, chararr-8); //create the string
byte[] des16 = new byte[16];
....
byte d = des16[8];
Unless you use unsafe code you cannot retrieve a pointer.
#JeffMercado, Thanks for opening my eyes.
In c++:
byte des16[16];
byte *d = des16+8;
In c#:
byte[] des16 = new byte[16];
byte[] b = new byte[8];
System.Array.Copy(des16, 8, b, 0, 8);
Pointers are basically getting converted. We can change it to an collection in c# .
In c++ if you need to change collection (string) to byte[] collection in c# you can execute code as below.
byte[] toBytes = Encoding.ASCII.GetBytes(somestring);
Related
I'm writing a software in C# which has as input a generic class made by primitive types and should generate a bytestream. This bytestream must be sent to a PLC buffer.
I read so many articles here in StackOverflow which basically go in three solutions:
Using binary formatter. This solution brings me a serializated binary stream (trying back Deserialize method returns me the original class) but checking the buffer I discovered that I can't find my data (see details below). Moreover I'm little bit worried by the fact that by checking Microsoft documentation the class is deprecated.
Using binary writer. This works correctly, but having a lot of different class declarations I needs to use Reflections in order retrieve dinamically each type and serialize it and it sounds a little bit too complicated to me (I'm leaving it as a "plan b" solution).
Using TypeDescriptor to convert the object. It doesn't work at all and Runtime engine returns "TypeConverter' is unable to convert X class"
Binary formatter code try is as follows:
TYPE_S_TESTA test = new TYPE_S_TESTA();
test.b_tipo = 54;
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter(); // BinaryFormatter is deprecated
bf.Serialize(ms, test);
ms.Seek(0, SeekOrigin.Begin);
byte[] test3 = ms.ToArray();
}
Class to serialize is defined as follows:
[Serializable]
public class TYPE_S_TESTA
{
public short b_tipo;
public char b_modo;
public char b_area;
public char b_sorgente;
public char b_destinatario;
public short w_lunghezza;
public short w_contatore;
public short w_turno;
public short w_tempo;
}
I already defined one value in my class as per test purposes. I expected a 14 bytes array with '54' inside (btw, another question is, what's the serialization order? I need exactly the same order as my definition). What I see with debugger on test3 buffer is instead:
_buffer {byte[512]} byte[]
[0] 0 byte
[1] 1 byte
[2] 0 byte
[3] 0 byte
[4] 0 byte
[5] 255 byte
[6] 255 byte
[7] 255 byte
[8] 255 byte
[9] 1 byte
[10] 0 byte
[11] 0 byte
[12] 0 byte
[13] 0 byte
[14] 0 byte
[15] 0 byte
[16] 0 byte
[17] 12 byte
[18] 2 byte
[19] 0 byte
[20] 0 byte
[21] 0 byte
[22] 71 byte
[23] 70 byte
[24] 97 byte
[25] 99 byte
So, no trace of my 54 and a 512 bytes buffer (why is it so big?).
You can declare TYPE_S_TESTA as follows:
using System.Runtime.InteropServices
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TYPE_S_TESTA
{
public short b_tipo;
public char b_modo;
public char b_area;
public char b_sorgente;
public char b_destinatario;
public short w_lunghezza;
public short w_contatore;
public short w_turno;
public short w_tempo;
}
You can convert an instance of a TYPE_S_TESTA to a byte array like this:
TYPE_S_TESTA test = new TYPE_S_TESTA();
test.b_tipo = 54;
int size = Marshal.SizeOf(typeof(TYPE_S_TESTA));
byte[] test3 = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(test, ptr, true);
Marshal.Copy(ptr, test3, 0, size);
I have 2 bytes that should populate this way:
first number (4b) second number (12b)
So 4 bit can be between 1-15
And 12 bit can be between 1-50
So i have this Bytes Array:
byte[] packetArrayBytes = new byte[Length];
The way I've understood the question is that you've got these two (presumably) unsigned integers a and b:
(I'll be writing them in hexadecimal to make it easier to read)
a: 0x0000000X
b: 0x00000XXX
Where a is the 4-bit number and b is the 12-bit one, with the Xs marking the bits containing the relevant values.
You want to store them in two separate 8-bit chunks: c: 0x00 and d: 0x00
So you need to shift the bits into position, like this:
byte[] packetArrayBytes = new byte[2];
uint intA = 0xF; // Allowed range is 0-15 (0x0-0xF)
uint intB = 0xABC; // Allowed range is 0-4095 (0x0-0xFFF)
// Need to convert from uint to bytes:
byte[] bytesA = BitConverter.GetBytes(intA);
byte[] bytesB = BitConverter.GetBytes(intB);
byte a = bytesA[0]; // a is 0x0F
byte b = bytesB[1]; // b is 0x0A
int c = 0x00; // c is 0x00
int d = bytesB[0]; // d is 0xBC
// Mask out 4 least significant bits of a,
// then shift 4 bits left to place them in the most significant bits (of the byte),
// then OR them into c.
c |= (a & 0x0F) << 4; // c is now 0xF0
// Mask out 4 least significant bits of b,
// then OR them into c.
c |= b & 0x0F; // c is now 0xFA
packetArrayBytes[0] = (Byte)c;
packetArrayBytes[1] = (Byte)d;
Console.WriteLine(BitConverter.ToString(packetArrayBytes)); // Prints "FA-BC"
After doing these operations, the values of a and b should be placed in the bytes c and d like this:
c: 0xFA d: 0xBC. Which you can then place into your array.
To get the values back you just do these same operations in reverse.
If a and b are signed values, I believe the same operations work, but you'll have to make sure you're not interpreting them as unsigned when reading the data back into numbers.
I have a byte array recived from Cpp program.
arr[0..3] // a real32,
arr[4] // a uint8,
How can I interpret arr[4] as int?
(uint)arr[4] // Err: can't implicitly convert string to int.
BitConverter.ToUint16(arr[4]) // Err: Invalid argument.
buff[0+4] as int // Err: must be reference or nullable type
Do I have to zero consecutive byte to interpret it as a UInt16?
OK, here is the confusion. Initially, I defined my class.
byte[] buff;
buff = getSerialBuffer();
public class Reading{
public string scale_id;
public string measure;
public int measure_revised;
public float wt;
}
rd = new Reading();
// !! here is the confusion... !!
// Err: Can't implicitly convert 'string' to 'int'
rd.measure = string.Format("{0}", buff[0 + 4]);
// then I thought, maybe I should convert buff[4] to int first ?
// I throw all forms of conversion here, non worked.
// but, later it turns out:
rd.measure_revised = buff[0+4]; // just ok.
So basically, I don't understand why this happens
rd.measure = string.Format("{0}", buff[0 + 4]);
//Err: Can't implicitly convert 'string' to 'int'
If buff[4] is a byte and byte is uint8, what does it mean by can't implicitly convert string to int ?... It confuses me.
You were almost there. Assuming you wanted a 32-bit int from the first 4 bytes (it's hard to interpret your question):
BitConverter.ToInt32(arr, 0);
This says to take the 4 bytes from arr, starting at index 0, and turn them into a 32-bit int. (docs)
Note that BitConverter uses the endianness of the computer, so on x86/x64 this will be little-endian.
If you want to use an explicit endianness, you'll need to construct the int by hand:
int littleEndian = arr[0] | (arr[1] << 8) | (arr[2] << 16) | (arr[3] << 24);
int bigEndian = arr[3] | (arr[2] << 8) | (arr[1] << 16) | (arr[0] << 24);
If instead you wanted a 32-bit floating-point number from the first 4 bytes, see Dmitry Bychenko's answer.
If I've understood you right you have byte (not string) array
byte[] arr = new byte[] {
182, 243, 157, 63, // Real32 - C# Single or float (e.g. 1.234f)
123 // uInt8 - C# byte (e.g. 123)
};
To get float and byte back you can try BitConverter
// read float / single starting from 0th byte
float realPart = BitConverter.ToSingle(arr, 0);
byte bytePart = arr[4];
Console.Write($"Real Part: {realPart}; Integer Part: {bytePart}");
Outcome:
Real Part: 1.234; Integer Part: 123
Same idea (BitConverter class) if we want to encode arr:
float realPart = 1.234f;
byte bytePart = 123;
byte[] arr =
BitConverter.GetBytes(realPart)
.Concat(new byte[] { bytePart })
.ToArray();
Console.Write(string.Join(" ", arr));
Outcome:
182 243 157 63 123
I have a control that has a byte array in it.
Every now and then there are two bytes that tell me some info about number of future items in the array.
So as an example I could have:
...
...
Item [4] = 7
Item [5] = 0
...
...
The value of this is clearly 7.
But what about this?
...
...
Item [4] = 0
Item [5] = 7
...
...
Any idea on what that equates to (as an normal int)?
I went to binary and thought it may be 11100000000 which equals 1792. But I don't know if that is how it really works (ie does it use the whole 8 items for the byte).
Is there any way to know this with out testing?
Note: I am using C# 3.0 and visual studio 2008
BitConverter can easily convert the two bytes in a two-byte integer value:
// assumes byte[] Item = someObject.GetBytes():
short num = BitConverter.ToInt16(Item, 4); // makes a short
// out of Item[4] and Item[5]
A two-byte number has a low and a high byte. The high byte is worth 256 times as much as the low byte:
value = 256 * high + low;
So, for high=0 and low=7, the value is 7. But for high=7 and low=0, the value becomes 1792.
This of course assumes that the number is a simple 16-bit integer. If it's anything fancier, the above won't be enough. Then you need more knowledge about how the number is encoded, in order to decode it.
The order in which the high and low bytes appear is determined by the endianness of the byte stream. In big-endian, you will see high before low (at a lower address), in little-endian it's the other way around.
You say "this value is clearly 7", but it depends entirely on the encoding. If we assume full-width bytes, then in little-endian, yes; 7, 0 is 7. But in big endian it isn't.
For little-endian, what you want is
int i = byte[i] | (byte[i+1] << 8);
and for big-endian:
int i = (byte[i] << 8) | byte[i+1];
But other encoding schemes are available; for example, some schemes use 7-bit arithmetic, with the 8th bit as a continuation bit. Some schemes (UTF-8) put all the continuation bits in the first byte (so the first has only limited room for data bits), and 8 bits for the rest in the sequence.
If you simply want to put those two bytes next to each other in binary format, and see what that big number is in decimal, then you need to use this code:
if (BitConverter.IsLittleEndian)
{
byte[] tempByteArray = new byte[2] { Item[5], Item[4] };
ushort num = BitConverter.ToUInt16(tempByteArray, 0);
}
else
{
ushort num = BitConverter.ToUInt16(Item, 4);
}
If you use short num = BitConverter.ToInt16(Item, 4); as seen in the accepted answer, you are assuming that the first bit of those two bytes is the sign bit (1 = negative and 0 = positive). That answer also assumes you are using a big endian system. See this for more info on the sign bit.
If those bytes are the "parts" of an integer it works like that. But beware, that the order of bytes is platform specific and that it also depends on the length of the integer (16 bit=2 bytes, 32 bit=4bytes, ...)
In case that item[5] is the MSB
ushort result = BitConverter.ToUInt16(new byte[2] { Item[5], Item[4] }, 0);
int result = 256 * Item[5] + Item[4];
Language : C#
Basically i have a Byte array which contains hexadecimal contents.
I want to convert it into a String and the hexadecimal contents should also be converted into Decimal contents.
My final string should contain Equivalent Decimal Values of the Hexa Decimal values contained in the initial Byte Array.
I converted byte array to string using
System.Text.Encoding.GetEncoding(1251).GetString
But how to convert the Hex to Decimal ?
Even if we can do it in multiple steps it is not a problem.
sorry to ask silly doubts , please Spare.
Thanks in Advance!
It's not entirely clear what you mean.
Byte arrays just contain byte values - they're just numbers. In other words:
byte x = 0x20;
byte y = 32;
are exactly the same - they both just set the value to be 32.
Now, if you want to convert a byte array into a number, look at BitConverter and its methods like BitConverter.ToInt32. That will convert the byte array into a number (an int in that particular case) - you can then just call ToString() on the number to get a decimal representation as a string.
How many bytes is your original data? That will be a key factor in determining which BitConverter method to call. You will also need to know the endianness of the data - if BitConverter in "normal" .NET is little endian; you might be interested in the EndianBitConverter class in my MiscUtil library if your data is really big-endian.
If your array really contains the character codes of the hexadecimal representation of numbers, then you don't have to bother with decoding. As the character codes for those characters are the same in all regular encodings, you can just cast the bytes to characters.
I wrote an extension that parses a stream of characters into a stream of bytes:
static class Hex {
public static IEnumerable<byte> ParseHex(this IEnumerable<char> chars) {
int buffer = 0;
bool first = true;
foreach (char c in chars) {
int b = (c - '0') % 32;
if (b > 9) b -= 7;
if (first) {
buffer |= b << 4;
} else {
yield return (byte)(buffer | b);
buffer = 0;
}
first = !first;
}
if (!first) {
yield return (byte)buffer;
}
}
}
(If someone recognises part of the code, it's based on my code in this answer.)
Usage:
byte[] data = { 48, 70, 51, 67, 70, 56, 48, 55, 57, 49 };
string result = string.Join(",",
data.Cast<char>().ParseHex().Select(b => b.ToString()).ToArray()
);
I'm a little unsure what you're trying to do. Are you trying to create a comma separated string of the decimal numbers - e.g:
byte[] hexValues = { 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF };
string decimalValuesAsStringList = string.Join(",", hexValues.Select(i => i.ToString()).ToArray());
...or like this:
char[] hexCharacters = { '9', 'A', 'B', 'C', 'D', 'E', 'F' };
byte[] hexValues = hexCharacters.Select(c => Convert.ToByte(c)).ToArray();
string decimalValuesAsStringList = string.Join(",", hexValues.Select(i => Convert.ToInt32(((char)i).ToString(), 16).ToString()).ToArray());