Search code examples
c#byteascii

byte[] with ASCII values to string to int


So someone took int value, converted it to string then converted it to ASCII values and then finally to byte[] with inconsistent length 1 - 4 bytes.

e.g. 100 -> "100" -> { 49, 48, 48 }.

Now I need that int value and I did it like this:

{ 49, 48, 48 } -> '1' + '0' + '0' -> "100" -> 100

                switch (header[25].Count)
                {
                    case 1:
                        hex = "" + (char)header[25][0];
                        amountOfData = Convert.ToInt32(hex, 16);
                        break;

                    case 2:
                        hex = "" + (char)header[25][0] + (char)header[25][1];
                        amountOfData = Convert.ToInt32(hex, 16);
                        break;

                    case 3:
                        hex = "" + (char)header[25][0] + (char)header[25][1] + (char)header[25][2];
                        amountOfData = Convert.ToInt32(hex, 16);
                        break;

                    case 4:
                        hex = "" + (char)header[25][0] + (char)header[25][1] + (char)header[25][2] + (char)header[25][3];
                        amountOfData = Convert.ToInt32(hex, 16); ;
                        break;

                    default:
                        break;
                }

but maybe there is better solution...

EDIT: sorry for not mentioning that, but header is List<List<byte>>


Solution

  • You can use library functions to parse from byte-like data to primitives; you're talking about ASCII, which means that Utf8Parser will work fine for us (all ASCII is also valid UTF8, although the reverse is obviously not true); normally, we would expect that header[25] is a byte[], a segment there-of, or some other raw binary source, but: ultimately, something like:

    var span = new ReadOnlySpan<byte>(header[25], 0, header[25].Count);
    if (!Utf8Parser.TryParse(span, out int amountOfData, out _))
        ThrowSomeError(); // not an integer
    

    If header[25] is something less convenient (like a List<byte> - I notice that in your example, your header[25] has a .Count not a .Length, which suggests it isn't a byte[]), then you can always either stackalloc a local buffer and copy the data out, or you can peek inside the list with CollectionMarshal.AsSpan<T>(List<T>), which returns a Span<T> from the underlying data:

    var span = CollectionMarshal.AsSpan(header[25]);
    if (!Utf8Parser.TryParse(span, out int amountOfData, out _))
        ThrowSomeError(); // not an integer
    

    As a runnable example that just shows the API:

    using System;
    using System.Buffers.Text;
    
    Span<byte> span = stackalloc byte[]  { 49, 48, 48 };
    if (!Utf8Parser.TryParse(span, out int amountOfData, out _))
        throw new FormatException();
    Console.WriteLine(amountOfData); // 100