2

I have a file with a string "40070", I read it and transform it to a ReadonlySpan<byte> variable with 52, 48, 48, 55, 48 inside. This Span represents the number 40070. How can I cast/transform that ReadonlySpan<byte> back to an int?

Thanks

Fritjof Berggren
  • 3,178
  • 5
  • 35
  • 57
  • Isn't it the same as? https://stackoverflow.com/questions/21639586/converting-byte-array-to-int - answer 4 seems promosing – Rand Random May 02 '23 at 09:44
  • 2
    Why does your span have 5 bytes when you want a 4 byte `int`? Do you want to ignore the last byte or something? – Sweeper May 02 '23 at 09:45
  • 1
    Either way, [this](https://stackoverflow.com/q/54271885/5133585) should help, if not a dupe. – Sweeper May 02 '23 at 09:46
  • 1
    Because the ReadonlySpan was sliced from a string, so that byte in theory is a char type – Fritjof Berggren May 02 '23 at 09:48
  • Doesn't really output the "desired" result: https://dotnetfiddle.net/LvBYQV – Rand Random May 02 '23 at 09:51
  • 1
    @Sweeper asker wants the bytes interpreted as ASCII character codes! – AakashM May 02 '23 at 09:51
  • You are probably not looking for samething like this https://dotnetfiddle.net/OpVQXp – Vojtěch Dohnal May 02 '23 at 09:52
  • 1
    why aren't you looking for `ReadOnlySpan` to `string`? and than simply parse the `string` to `int`? https://dotnetfiddle.net/dg4u8o – Rand Random May 02 '23 at 09:54
  • 1
    I'm extracting numbers from a huge file, so whenever I find a ReadonlySpan that represents a number, I have to cast it to an int. Dohnal, your solution works, but I'm wondering if there is not a one line solution that relies in a .Net API – Fritjof Berggren May 02 '23 at 09:55
  • prolly because 1) it takes memory 2) even worst .. C# string are 2 byte long 3) it takes time .. – Selvin May 02 '23 at 09:55
  • Thanks, and trying not to be annoying, but is there any way where we don't allocate any memory and rely on Span instrinsics? – Fritjof Berggren May 02 '23 at 09:59
  • 1
    `System.Buffers.Text.Utf8Parser` ? – Selvin May 02 '23 at 10:00
  • if you had `ReadOnlySpan` you could have used `TryFormat` - https://learn.microsoft.com/en-us/dotnet/api/system.int32.tryformat?view=net-7.0 – Rand Random May 02 '23 at 10:04
  • System.Buffers.Text.Utf8Parser worked like a charm, thanks! – Fritjof Berggren May 02 '23 at 10:05
  • 2
    But generally it is the Vojtěch Dohnal code :D https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Parser/Utf8Parser.Integer.Unsigned.N.cs#L53 ... so if you know that your span contains only integer as string without sign/dots/etc it will be faster – Selvin May 02 '23 at 10:06
  • 2
    out of curiosity did you run the horses, or just used the most fancy looking one? https://ericlippert.com/2012/12/17/performance-rant/ – Rand Random May 02 '23 at 10:45
  • 2
    @RandRandom Accepted is the fastest - see here https://dotnetfiddle.net/HEenrR – Vojtěch Dohnal May 03 '23 at 07:19
  • 1
    @RandRandom But not really, the results in fiddle are wrong in debug, the first code I posted in comments was in fact the fastest https://stackoverflow.com/q/76162739/2224701. – Vojtěch Dohnal May 03 '23 at 11:41

2 Answers2

9
ReadOnlySpan<byte> data = stackalloc byte[] { 52, 48, 48, 55, 48 };
// ^^^ or however you're getting your span; that part doesn't matter

if (System.Buffers.Text.Utf8Parser.TryParse(data, out int value, out int bytes))
{
    Console.WriteLine($"Parsed {bytes} bytes into value: {value}");
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
1

You can read the initial data as chars, or convert the bytes into span of chars and use int.Parse/TryParse:

ReadOnlySpan<byte> span = new byte[] { 52, 48, 48, 55, 48 };
Span<char> chars = stackalloc char[span.Length];
Encoding.ASCII.GetChars(span, chars);
var result = int.Parse(chars);
Console.WriteLine(result); // prints "40070"
Guru Stron
  • 102,774
  • 10
  • 95
  • 132