-2

I have an incoming string 68016101061B4A60193390662046804020422044204000420040402060226024676DB16 and I want to convert into 0x68 0x01 0x61 0x01 0x06 0x1B 0x4A 0x60 0x0B 0x86 0xE8 0x46 0x04 0x68 0x04 0x02 0x04 0x22 0x04 0x42 0x04 0x00 0x04 0x20 0x04 0x40 0x02 0x06 0x02, 0x26 0x02 0x46 0x76 0xDB 0x16 but in bytes. I want to write these bytes into a serial port.

port.Write(bytes, 0, bytes.Length);

Update 1

Below is the byte array that I am sending by hard coding it

var dataItems = new byte[] { 0x68, 0x01, 0x61, 0x01, 0x06, 0x1B, 0x4A, 0x60, 0x0B, 0x86, 0xE8, 0x46, 0x04, 0x68, 0x04, 0x02,
            0x04, 0x22, 0x04, 0x42, 0x04, 0x00, 0x04, 0x20, 0x04, 0x40, 0x02, 0x06, 0x02, 0x26, 0x02, 0x46 ,0x76 ,0xDB ,0x16 };

It gives me below array

enter image description here

How can I convert it?

Moeez
  • 494
  • 9
  • 55
  • 147
  • 1
    What have you tried so far to convert it? – Pavel Anikhouski May 17 '20 at 19:42
  • 1
    This classic question generally answers all my questions about this subject (even though the bulk of the question and it's answers deal with the opposite transformation) https://stackoverflow.com/questions/1139957/convert-integer-to-hexadecimal-and-back-again – Flydog57 May 17 '20 at 20:41
  • This is already answered many times https://stackoverflow.com/questions/311165/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-and-vice-versa – 2zemec May 17 '20 at 20:56

3 Answers3

2

You can use a regular expression to do this:

var regex = new Regex(@"(\d{2})");

string aString = "040204220442040004200404020602260246";
string replaced = regex.Replace(aString, "x$1 ");

Fiddle

EDIT It seems like you need bytes instead of a string, you can use one of the Linq based answers suggested here or a simple loop:

if ((aString.Length % 2) != 0)
{
    // Handle invalid input
}

var bytes = new byte[aString.Length / 2];

int index = 0;
for (int i = 0; i < aString.Length; i += 2)
{
    string digits = aString.Substring(i, 2);
    byte aByte = (byte)int.Parse(digits, NumberStyles.HexNumber);

    bytes[index++] = aByte;
}

port.Write(bytes, 0, bytes.Length);

Note that if GC pressure became an issue, you could use ReadOnlySpan<char>.

Fiddle

vc 74
  • 37,131
  • 7
  • 73
  • 89
  • It's in string I want it in bytes? – Moeez May 17 '20 at 20:09
  • input can be in even and odd – Moeez May 18 '20 at 09:33
  • @Faisal What do you mean? Bytes not consistently serialized as 2 chars? in this case there's no way to parse your string. For example, does 222 mean [2, 2, 2], [22, 2] or [2, 22]? Additionally, looking at the second entry (01) it seems like they are always serialized as 2 chars. – vc 74 May 18 '20 at 09:37
  • `222` means `2,2,2`. – Moeez May 18 '20 at 09:43
  • My full string is `68016101061B4A601933906620468040204220442040004200404020602260246046676DB16` – Moeez May 18 '20 at 09:44
  • Then how do you express 22 followed by a 2? – vc 74 May 18 '20 at 09:44
  • The number of bytes per char will be 1. – Moeez May 18 '20 at 09:45
  • Your initial string was not hex, if you want a quick and clear answer please specify all the aspects of your question in the initial post, having to guess what you want is a waste of time for the ones replying – vc 74 May 18 '20 at 09:51
  • "The number of bytes per char will be 1" so the first 3 bytes in your string are [6, 8, 0]? – vc 74 May 18 '20 at 09:54
  • I want to send those bytes via serial port following the array that I suggested – Moeez May 18 '20 at 09:58
  • So all your bytes are serialized as 2 consecutive characters, then the code should work – vc 74 May 18 '20 at 09:58
  • The fact that you want to send bytes to a port is irrelevant to the question, you just want to deserialize an array of bytes from a string – vc 74 May 18 '20 at 10:00
  • The string values `0402042204420400042004040206022602460466` can be less or more than that depending upon the parameters I want to read so I want to have a method that will convert any amount of strings not just a fixed amount – Moeez May 18 '20 at 10:03
  • This code works with any string, provided each byte is encoded as 2 chars. Your example contains 71 chars and 71 is not a multiple of 2 therefore your input is invalid – vc 74 May 18 '20 at 10:05
  • Atually it's in `75`. Can I handle the odd numbers ? – Moeez May 18 '20 at 10:17
  • The bytes up to position 16 (0 based) seem to follow the 2 chars -> 1 byte rule, then at position 16 , a '19' is supposed to be converted to '0B': how is that conversion supposed to happen? – vc 74 May 19 '20 at 06:34
1

In Linq:

string src = "040204220442040004200404020602260246";
string res = Enumerable.Range(0, src.Length)
                       .Where(i => i % 2 == 0)
                       .Aggregate<int, string, string>("", (s, i) => s + " 0x" + src.Substring(i, 2), (s) => s.Trim());

or - if the input string is very long - to better the performance:

 string res = Enumerable.Range(0, src.Length)
                        .Where(i => i % 2 == 0)
                        .Aggregate<int, StringBuilder, string>(new StringBuilder(), (sb, i) => sb.Append(" 0x").Append(src.Substring(i, 2)), (sb) => sb.ToString().Trim());

in both cases the res contains "0x04 0x02 0x04 0x22 0x04 0x42 0x04 0x00 0x04 0x20 0x04 0x04 0x02 0x06 0x02 0x26 0x02 0x46"

If you want the result as an array of bytes AND to handle input strings with an uneven number of digits as well it could be done as follwing:

string src = "040204220442040004200404020602260246";
if (src.Length % 2 == 1) src += "0";
byte[] res = Enumerable.Range(0, src.Length)
                       .Where(i => i % 2 == 0)
                       .Select(i => Byte.Parse(src.Substring(i, 2), System.Globalization.NumberStyles.AllowHexSpecifier))
                       .ToArray();
Anders H
  • 391
  • 4
  • 11
  • with odd number of values i am getting `Index and length must refer to a location within the string. Parameter name: length` – Moeez May 17 '20 at 20:32
  • 1
    If the inputstring does not contains an even number of digits, what do you expect the result string to be? Depending on your expectations the linq expression can be fixed to support that scenario as well – Anders H May 17 '20 at 20:39
  • string can be even or can be odd. – Moeez May 17 '20 at 20:40
  • 1
    If your input string with an odd number of digits ends with on for instance 7, would you expect the last element in the result string to be 0x07 or 0x70 or simply 0x7? – Anders H May 17 '20 at 20:42
  • Take my question example the last string is `16` and it's hex should be `0x16` – Moeez May 17 '20 at 20:45
  • `01` will be `0x01` – Moeez May 17 '20 at 20:46
  • 1
    If you input string has an uneven number of digits - for instance: "98567". How do you expect that string to be converted? – Anders H May 17 '20 at 20:51
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/214074/discussion-between-faisal-and-anders-hyldahl). – Moeez May 17 '20 at 20:56
0

If you want to use pure LINQ, you can do something along the lines of

data
    .Select((x,i) => (Index: i, Value: x))
    .GroupBy(tuple => tuple.Index / 2, tuple => tuple.Value, (_,values) => "0x" + string.Join("",values))
    .Select(x => Convert.ToByte(x, 16))
    .ToArray();

if you want a ridiculous one-liner.

  • I want to have it in byte hex. Need to send data to a port – Moeez May 17 '20 at 20:08
  • Changed to convert to a byte array. – Jason Steinhauser May 17 '20 at 20:20
  • 1
    Which byte would be halved then? In the example `12345` would I expect bits of `0x01 0x23 0x45`, `0x12 0x34 0x5`, or `0x12 0x34 0x50`. With an odd number of nibbles and no explanation for how to handle that odd nibble, there's no solid way of answering your question. – Jason Steinhauser May 17 '20 at 22:44
  • In my question, `68` ,`01` ..... `16`, each is of 1 byte. so `68` would become `0x68`, `01` into `0x01` and so on. – Moeez May 18 '20 at 04:33
  • Yes, this solution works for an odd number of bytes. There will still be an even number of characters, which is what the `GroupBy` cares about – Jason Steinhauser May 18 '20 at 19:44
  • It's not giving me correct bytes. It should be `35` but I am getting `38`. You can see my updated question? – Moeez May 19 '20 at 04:21