Home > Net >  Get base64-encoded string from ReadOnlySequence<byte>
Get base64-encoded string from ReadOnlySequence<byte>

Time:10-21

Given ReadOnlySequence<byte>, how to get its base64-encoded representation? There's ReadOnlySpan<Byte> overload, but sequence is... a sequence of spans, not a single span.

I know, that it's possible to make an array from sequence, but this is what I want to avoid: I use RecyclableMemoryStream and trying to avoid extra memory allocations.

Any solution?

CodePudding user response:

You need something which can keep state as you pass in different blocks of bytes. That thing is a ToBase64Transform.

Annoyingly, none of the methods on it take a Memory or ROS (apart from the async ones) -- they're all array-based. I guess you could have a scratch array which you copy chunks into, then pass those chunks to ToBase64Transform, but at that point you might as well just use Convert.ToBase64String on each chunk and concatenate the results.

You could pass ToBase64Transform to a CryptoStream. You could then call Stream.Write(ReadOnlySpan<byte>), but that's implemented to copy the span into an array (and CryptoStream doesn't override this), which is what you're trying to avoid.

However, CryptoStream does override WriteByte, so that might be your best bet.

Something like:

using var writer = new StringWriter();
using (var stream = new CryptoStream(writer, new ToBase64Transform(), CryptoStreamMode.Write))
{
    foreach (var memory in readOnlySequence)
    {
        if (MemoryMarshal.TryGetArray(memory, out var segment)) 
        {
            stream.Write(segment.Array, segment.Offset, segment.Count);
        }
        else
        {
            var span = memory.Span;
            for (int i = 0; i < span.Length; i  )
            {
                stream.WriteByte(span[i]);
            }
        }
    }
}

string result = writer.ToString();

At this point, though, it's looking like it might be neater to just use Base64.EncodeToUtf8 and a StringWriter yourself, manually...

  • Related