Read socket data Hex instead of Ascii - c#

I am receiving data from a cnc machine every 5 seconds. Length of the data is 66 bytes. And every two byte has a special meaning according to the guide that I have. The device sends the data over socket to a specific ip and port. I have been told that I should read the data as hex instead of ascii.
This line of code returns
string data = Encoding.ASCII.GetString(data.buffer,0,66);
this;
"\0\u0004\0\u0001\0\0\0\0\0\0\0\0\0\0\0\0\0\r\0\r\0\0\0\0\0\0:a\u0002#\0?\0`\u001b?\u0015U\0\0\0\0\u0001\u0010\0\u0018\0\0\u000f\a\0\0\0\0\0\0\0\0\0\0\0\0\0\0u/"
and of course it is not useful to me.
I did tried to convert byte array to the hex string with that code;
StringBuilder sb = new StringBuilder();
foreach (byte b in buffer)
sb.Append(b.ToString("X2"));
string hexString = sb.ToString();
And got result as
00040001000000000000000000020000000000000000000000003A9D023F00A000601B841555000000000110001800000F070000000000000000000000000000752F
And when I try to convert this result as string, no success, nothing meaningfull.
GOAL
What I am trying to achieve is, read the incoming socket data as hex and use every two byte as a word to match a value. For example first 2 byte should match either 0 or 1. With i have it returns ? (question mark)
Thank you.

I have been told that I should read the data as hex instead of ascii
My gut feeling is this statement has been misquoted or misunderstood. There is no value in processing binary data as string hex representation just as there is no value in converting it to ascii... The only sane way to process binary data, is in binary unless you have a meaningful way to convert it.
You mention you need word (2byte) groupings, you could just convert this to an array of short, or ushort depending on your needs
var bytes = new byte[66];
var shortArray = new short[bytes.Length / 2];
Buffer.BlockCopy(bytes, 0, shortArray, 0, bytes.Length);
or
for (int i = 0; i < shortArray.Length; i++)
shortArray[i] = BitConverter.ToInt16(bytes[(i*2)..(i*2+2)]);
Disclaimer : This is just an example, be very careful of the endianess of your data, there are other ways to do this

Related

How can i encode a string to UTF-8 to a pre existing byte array?

I have a simple bit of code that converts a C# string by encoding it to UTF-8 then creating a byte array from it. But i am wondering how can i encode to UTF-8 using a byte array i have already made at a starting index?
So this is how i am currently encoding and getting the resulting byte array:
byte[] result = Encoding.UTF8.GetBytes(myString);
But I have a byte array premade that i would prefer to write to at a specific index if that makes sense. Is there any built in method to do this, if not how would i go about it ?
GetBytes has another overload that writes to existing array:
byte[] bytes = new byte[1000]; // sample, make sure it has enough space
var specificIndex = 0;
var actualByteCount = Encoding.UTF8.GetBytes(
myString, 0, myString.Length, bytes, specificIndex);
Don't forget to handle result to know how many bytes in the array actually represent string (actualByteCount)
Note you may need to use GetByteCount to get correct array size or adjust number of characters to convert to fit into your buffer.
First you will need to convert your bytes into Base64String then convert that into bytes. Likes this:
byte[] random = new byte[] { 0x00C9, 0x00C9, 0x00C9 };
byte[] encodedBytes = Encoding.UTF8.GetBytes(Convert.ToBase64String(random));

Sending Ints as bytes from arduino to C# program fails

I'm working on a program in VS2010 C#. It has a GUI that is used to interact with an Arduino over the serial port.
The issue that I'm having is sending a byte value larger than 128(???) from the arduino to the program. I get an integer value on the arduino, break it into highBite and lowByte, and send each one, the reassemble on the other side.
If I send 600, it will send highByte of 2 and lowByte of 88, and it reassembles to 600 properly via bitshiting <<8 of highByte.
If I try to send 700 which should be 188 and 2, then I am seeing the 188 show in in C# as 63. Why???
A byte should be unsigned on both arduino and C#, so I'm not sure what is going wrong.
Arduino code (relevant parts): (0x43 signals to C# which data packet it is receiving)
byte bytesToSend[3] = {0x43, byte(88), byte(2)}; // 600 broken down to high and low bytes
Serial.write(bytesToSend, 3); // send three bytes
Serial.println(); //send line break to terminate transmission
byte bytesToSend[3] = {0x43, byte(188), byte(2)}; // 700 broken down to high and low bytes
Serial.write(bytesToSend, 3); // send three bytes
Serial.println(); //send line break to terminate transmission
C# code: (relevant parts - May have missed a syntax or two since I cut/trimmed and pasted...)
string inString = "";
inString = port.ReadLine(); // read a line of data from the serial port
inString = inString.Trim(); //remove newline
byte[] buf = new byte[15]; // reserve space for incoming data
buf = System.Text.Encoding.ASCII.GetBytes(inString); //convert string to byte array I've tried a block copy here, but it didn't work either...
Console.Write("Data received: H: {0}, L: {1}. =", buf[2], buf[1]); //display high and low bytes
Console.WriteLine(Convert.ToUInt32((buf[2] << 8) + buf[1])); //display combined value
And this is what I get in the serial monitor where it writes out the values:
Data received: H: 2, L: 88. = 600
Data received: H: 2, L: 63. = 575
The low byte value gets changed or mis-interpreted from 188 to 63 somewhere in the process. What is causing this and how can I fix it? It seems to work fine when the byte value is below 128, but not when it is above.
I think this could be problem at your c# side code. You should debug this by printing the string which you are reading just after port.ReadLine(), to see what you are receiving.
Also I would suggest to use C# Read(Byte[], Int32, Int32), so that your data is read into Byte Array which is array of unsigned char. ReadLine() is reading data into string (array of char).
Your encoding is wrong. Change the line from:
buf = System.Text.Encoding.ASCII.GetBytes(inString);
to
buf = System.Text.Encoding.GetEncoding("Windows-1252").GetBytes(inString);
Better yet, when you instantiate your Port object just set the encoder property to this type.
...
SerialPort port = new SerialPort();
System.Text.Encoding encoder = System.Text.Encoding.GetEncoding("Windows-1252");
port.Encoding = encoder;
...
Remember that ASCII is 7-bit so you will truncate values that are greater than decimal 127. The 1252 encoding is 8 bit and is great for binary data. The table shown at MSDN shows the full symbol support for the encoding.
Why, in C#, reading full string - which will force you to deal with encodings, ... - and do post-process instead of parsing in time?
System.IO.BinaryReader bin_port=new System.IO.BinaryReader(port); //Use binary reader
int b;
int data16;
b=bin_port.ReadByte();
switch (b) {
case 0x43: //Read integer
data16=bin_port.ReadUInt16();
while (bin_port.ReadByte()!=0x0a); //Discard all bytes until LF
break;
}

Best way to convert file containing ASCII representations of bytes to real bytes C# .NET

I have a file containing some data (for example, "00927E2B112DB958......"). This data is a representation of bytes in ASCII form. The bytes are 8 bit, so 2 ASCII chars map to each byte that needs to go into the final output buffer array.
What is the best way to do this?
EDIT: What I am trying to do is go from a string that looks like "00DFFF" to a byte array of {0x00, 0xDF, 0xFF}, for example. I guess this wasn't clear.
Thanks!
private ICollection<byte> HexString2Ascii(string hexString)
{
var bytes = new List<byte>(hexString.Length / 2);
for (int i = 0; i <= hexString.Length - 2; i += 2)
bytes.Add(byte.Parse(hexString.Substring(i, 2), System.Globalization.NumberStyles.HexNumber));
return bytes;
}

Split a result from File.ReadAllBytes

My code here reads all the bytes of a image and stores it in the byte array. Is there a way to convert these bytes into ascii then split them up to 512-char(ascii char) long pieces? Like when you try splitting a string based on the length, you can do that. Can you do something similar to splitting this into 512 lengths? This is to send to the server.
byte[] imagesize;
imagesize = File.ReadAllBytes(#"C:\image.jpeg");
Console.Write(imagesize[1].ToString());
What I really want is to convert these bytes into plain ASCII format (Which in C# would be Encoding.ASCII), then split that long ASCII line from converting all the bytes into 512-char(?) long chunks into a byte array (byte[] chunks). So when I send the packets I can do
for(i=0; i<AmountOfChunks; i++)
{
Packet.payload = chunks[i];
//The "chunks" is the ASCII formated array.
}
If someone knows how to do this, it would greatly help. Thanks, if there's anything more, i'll try to explain it in more detail if i can.
If this is wrong, because i know a byte is 8-bit each. Then somehow to be able to do it, maybe the bytes into a list?
Not clear why you needs this, but you might be looking for Convert.ToBase64String() to get a string representation. For chunking you can just walk over the resulting string and split at the appropriate indexes:
byte[] imagesize = File.ReadAllBytes(#"C:\image.jpeg");
string base64String = Convert.ToBase64String(imagesize);
List<string> chunks = new List<string>();
for (int i = 0; i < base64String.Length; i+=512)
{
chunks.Add(base64String.Substring(i, Math.Min(512, base64String.Length - i)));
}
Try to make this
int i=0;
do
{
sendBytes = imagesize.Skip(512*i).Take(512).ToArray();
//Your function of send
i++;
}
while(imagesize.Count()-512*i>0)

Equivalent of sprintf in C#?

Is there something similar to sprintf() in C#?
I would for instance like to convert an integer to a 2-byte byte-array.
Something like:
int number = 17;
byte[] s = sprintf("%2c", number);
string s = string.Format("{0:00}", number)
The first 0 means "the first argument" (i.e. number); the 00 after the colon is the format specifier (2 numeric digits).
However, note that .NET strings are UTF-16, so a 2-character string is 4 bytes, not 2
(edit: question changed from string to byte[])
To get the bytes, use Encoding:
byte[] raw = Encoding.UTF8.GetBytes(s);
(obviously different encodings may give different results; UTF8 will give 2 bytes for this data)
Actually, a shorter version of the first bit is:
string s = number.ToString("00");
But the string.Format version is more flexible.
EDIT: I'm assuming that you want to convert the value of an integer to a byte array and not the value converted to a string first and then to a byte array (check marc's answer for the latter.)
To convert an int to a byte array you can use:
byte[] array = BitConverter.GetBytes(17);
but that will give you an array of 4 bytes and not 2 (since an int is 32 bits.)
To get an array of 2 bytes you should use:
byte[] array = BitConverter.GetBytes((short)17);
If you just want to convert the value 17 to two characters then use:
string result = string.Format("{0:00}", 17);
But as marc pointed out the result will consume 4 bytes since each character in .NET is 2 bytes (UTF-16) (including the two bytes that hold the string length it will be 6 bytes).
It turned out, that what I really wanted was this:
short number = 17;
System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream);
writer.Write(number);
writer.Flush();
The key here is the Write-function of the BinaryWriter class. It has 18 overloads, converting different formats to a byte array which it writes to the stream. In my case I have to make sure the number I want to write is kept in a short datatype, this will make the Write function write 2 bytes.

Categories