Convert.ToBase64String为字节[]抛出“ System.OutOfMemoryException”(文件:大尺寸)

时间:2018-10-05 11:16:49

标签: c# base64

我正在尝试将byte[]转换为 base64 字符串格式,以便可以将该信息发送给第三方。我的代码如下:

byte[] ByteArray = System.IO.File.ReadAllBytes(path);
string base64Encoded = System.Convert.ToBase64String(ByteArray);

我遇到以下错误:

  

引发了类型为'System.OutOfMemoryException'的异常。你是否可以   请帮我吗?

1 个答案:

答案 0 :(得分:1)

更新

我刚刚发现@PanagiotisKanavos的评论指向Is there a Base64Stream for .NET?。这基本上与我的以下代码尝试实现的功能相同(即,允许您处理文件而不必一次将整个内容保存在内存中),但没有自滚动代码的开销/风险/而是使用作业的标准.Net库方法。


原始

以下代码将创建一个新的临时文件,其中包含输入文件的Base64编码版本。

这应该减少内存占用,因为我们不是一次处理所有数据,而是一次处理几个字节。

为避免将输出保留在内存中,我将其推回了一个临时文件,该文件将返回。以后需要在其他过程中使用该数据时,需要对其进行流式处理(即再次避免一次使用所有这些数据)。

您还将注意到,我使用的是WriteLine而不是Write;这将引入非base64编码的字符(即换行符)。这是有意的,因此,如果您使用文本阅读器使用临时文件,则可以轻松地逐行处理它。
但是,您可以根据需要进行修改。

void Main()
{
    var inputFilePath = @"c:\temp\bigfile.zip";
    var convertedDataPath = ConvertToBase64TempFile(inputFilePath);
    Console.WriteLine($"Take a look in {convertedDataPath} for your converted data");
}

//inputFilePath = where your source file can be found.  This is not impacted by the below code
//bufferSizeInBytesDiv3  = how many bytes to read at a time (divided by 3); the larger this value the more memory is required, but the better you'll find performance.  The Div3 part is because we later multiple this by 3 / this ensures we never have to deal with remainders (i.e. since 3 bytes = 4 base64 chars)
public string ConvertToBase64TempFile(string inputFilePath, int bufferSizeInBytesDiv3 = 1024)
{
    var tempFilePath = System.IO.Path.GetTempFileName();
    using (var fileStream = File.Open(inputFilePath,FileMode.Open))
    {
        using (var reader = new BinaryReader(fileStream))
        {
            using (var writer = new StreamWriter(tempFilePath))
            {
                byte[] data;
                while ((data = reader.ReadBytes(bufferSizeInBytesDiv3 * 3)).Length > 0)
                {
                    writer.WriteLine(System.Convert.ToBase64String(data)); //NB: using WriteLine rather than Write; so when consuming this content consider removing line breaks (I've used this instead of write so you can easily stream the data in chunks later)
                }
            }
        }
    }
    return tempFilePath;
}