C# 解码大的Base64字符串

C# 解码大的Base64字符串,c#,base64,out-of-memory,C#,Base64,Out Of Memory,我有一个来自Web服务的输入字符串,它是一个大约70 MB大的base64编码字符串 我想将其解码成一个文件,并尝试了显而易见的方法:使用Convert.FromBase64String() 然而,这会产生一个OutOfMemoryException。经过一些阅读,我发现Convert方法与Base64有关 内存泄漏(毫无疑问,这是由于字符串的不可变性质和框架方法内部的一些糟糕设计造成的) 在System.Security.Cryptography命名空间中有一个方便的“流式”替换:FromB

我有一个来自Web服务的输入字符串,它是一个大约70 MB大的base64编码字符串

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

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

内存泄漏(毫无疑问,这是由于字符串的不可变性质和框架方法内部的一些糟糕设计造成的)

System.Security.Cryptography
命名空间中有一个方便的“流式”替换:
FromBase64Transform

所以,我决定尝试一下,但是我需要输入一个由
字节
组成的数组,我没有这个数组,我有一个字符串


如何将我拥有的
字符串
转换为
字节
s,而不在该转换中再次运行另一个
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();
}
如果用合适的
FileStream
替换
MemoryStream
,则可以直接流到文件而不是数组:

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();
}

响应是一个JSON响应,它使用
NewtonSoft.JSON
反序列化-它返回一个正确的对象。但是我想我必须为这种类型的响应创建一些例外,这样我就可以直接流式传输响应了……这肯定会更好。不过,平心而论:使用base64的主要原因是为了处理无法传输二进制文件的情况,例如由于格式问题、API限制等。如果您得到的是JSON,那么添加流式支持可能会带来更多麻烦(但如果您认为值得,您可以传输二进制文件并节省25%的带宽:))。不幸的是,Web服务不在我的控制之下。我必须处理从中得到的东西。众所周知,对大型对象堆的理解很差。今天,没有太多理由不在64位操作系统上运行web服务。标准错误是忘记删除抖动强制、项目+属性、编译选项卡。