如何在Convert.TryFromBase64String()中使用Span?

Mor*_*siu 3 c# base64 .net-core

我试图写一些try catchConvert.FromBase64String(),我发现它已经具有TryFromBase64String()方法。但是它需要3个参数:

public static bool TryFromBase64String(string s, Span<byte> bytes, out int bytesWritten);
Run Code Online (Sandbox Code Playgroud)

那我该怎么用 Span<byte> bytes呢?

我仅在文档中找到此内容,但没有适当的描述。也许这太明显了。

https://docs.microsoft.com/zh-cn/dotnet/api/system.convert.tryfrombase64string?view=netcore-2.1

感谢@Damien_The_Unbeliever和这篇文章,我发现了更多有关的信息Span。所以...

Span用于节省内存,因此不要调用太多。它可以存储数组或数组的一部分,但是我仍然不知道如何在该方法中使用它。

mar*_*sze 7

如果您只是暂时需要缓冲区,这是另一种方法,使用ArrayPool(以减少GC 压力):

// Minimum length that is guaranteed to fit all the data.
// We don't need the exact length, because the pool
// might return a larger buffer anyway.
var minLength = ((value.Length * 3) + 3) / 4;
var buffer = ArrayPool<byte>.Shared.Rent(minLength);
try
{
    // (buffer is implicitly cast to Span<byte>)
    if (Convert.TryFromBase64String(value, buffer, out var bytesWritten))
    {
        // do something with it...
        return Encoding.UTF8.GetString(buffer, 0, bytesWritten);
    }
    throw new FormatException("Invalid base-64 sequence.");
}
finally
{
    ArrayPool<byte>.Shared.Return(buffer);
}
Run Code Online (Sandbox Code Playgroud)


xan*_*tos 6

如链接的问题所述,System.Span<T>它是C#7.2的新功能(Convert.TryFromBase64String is a newer .NET Core feature)

要使用它,System.Span<>您必须安装一个nuget软件包:

Install-Package System.Memory
Run Code Online (Sandbox Code Playgroud)

然后使用它:

byte[] buffer = new byte[((b64string.Length * 3) + 3) / 4 -
    (b64string.Length > 0 && b64string[b64string.Length - 1] == '=' ?
        b64string.Length > 1 && b64string[b64string.Length - 2] == '=' ?
            2 : 1 : 0)];

int written;
bool success = Convert.TryFromBase64String(b64string, buffer, out written);
Run Code Online (Sandbox Code Playgroud)

b64string您的base-64字符串在哪里。buffer基于的长度,过于复杂的大小应该是缓冲区的确切长度b64string


Lou*_* G. 6

您可以像这样使用它,利用所有参数TryFromBase64String

public string DecodeUtf8Base64(string input)
{
  var bytes = new Span<byte>(new byte[256]); // 256 is arbitrary

  if (!Convert.TryFromBase64String(input, bytes, out var bytesWritten))
  {
    throw new InvalidOperationException("The input is not a valid base64 string");
  }

  return Encoding.UTF8.GetString(bytes.Slice(0, bytesWritten));
}
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用“stackalloc”来提高性能...尝试“Span&lt;byte&gt; bytes = stackalloc byte[256];” (2认同)
  • @marsze - 你是对的,你不想将可能很大的数组长度传递到“stackalloc”中。“stackalloc”的[文档](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc)给出了如何处理这个问题的示例。假设您已经定义: `const int MaxStackLimit = 1024;` 然后您可以根据请求的长度选择适当的分配模式: `Span&lt;byte&gt; buffer = inputLength &lt;= MaxStackLimit ? stackalloc 字节[MaxStackLimit] : 新字节[inputLength];` (2认同)