解码大型 Base64 字符串

Decode large Base64 strings

我有一个来自 WebService 的输入字符串,其形式为大约 70 MB 的大型 base64 编码字符串。

我想将其解码为一个文件,并尝试了显而易见的方法:使用 Convert.FromBase64String().

然而,这会产生 OutOfMemoryException。经过一番阅读,我发现 Convert 方法与 Base64

有关

leak memory (no doubt due to the immutable nature of strings and some poor design inside the framework methods) source

并且在 System.Security.Cryptography 命名空间中有一个方便的 "streamed" 替换:FromBase64Transform.

所以,我决定尝试一下,但我需要向方法输入一个 byte 数组,我没有 - 我有一个字符串。

如何在 that 转换中将没有 运行 的 string 转换为 bytes 到另一个 OutOfMemoryException又是?

您应该使用 Encoding.ASCII.GetBytes() 或类似工具将您的字符串转换回用于传输 base64 编码数据的原始 ASCII。

我很好奇您最初是如何从 WebService 收到字符串的。是否可以跳过到 .NET 字符串的转换并直接将接收到的字节传递给转换?这样效率会更高

尽管您可能可以将字符串转换为内存中的字节数组而不必担心内存使用,但您可以通过以下方式 转换:

var input = "abcdefghijklmnop";
byte[] output;
using (var ms = new MemoryStream())
using (var cs = new CryptoStream(ms, new FromBase64Transform(), CryptoStreamMode.Write))
using (var tr = new StreamWriter(cs))
{
    tr.Write(input);
    tr.Flush();
    output = ms.ToArray();
}

如果您将 MemoryStream 替换为合适的 FileStream,您可以直接流式传输到文件而不是数组:

var input = new string('a', 400000000);
byte[] output;
using (var ms = new FileStream(Guid.NewGuid().ToString() + ".bin", FileMode.Create))
using (var cs = new CryptoStream(ms, new FromBase64Transform(), CryptoStreamMode.Write))
using (var tr = new StreamWriter(cs))
{
    tr.Write(input);
    tr.Flush();
}