【问题标题】:Encode zip file to Base64将 zip 文件编码为 Base64
【发布时间】:2014-06-21 17:30:42
【问题描述】:

我想将 zip 文件解码为 base64 字符串。文件可以达到 100 MB 并获得 OutOfMemory 异常并重新启动 Visual Studio。我的编码:

public static string EncodeToBase64(string zipPath)
{
    using (FileStream fs = new FileStream(zipPath, FileMode.Open, FileAccess.Read))
    {
       byte[] filebytes = new byte[fs.Length];
       fs.Read(filebytes, 0, Convert.ToInt32(fs.Length));
       return Convert.ToBase64String(filebytes);
    }
}

我能做些什么来解决它?

【问题讨论】:

  • 100 MB 应该不是问题。你的内存满了吗?您还需要“代码中”的 base64 字符串还是将其保存/发送到某个地方?
  • 100MB 如果您一次又一次地这样做很容易成为问题
  • 我有很多内存不足,但在编码为 base64 时 RAM 会迅速增加。我用于保存和发送的 base64 字符串
  • 在一个 32 位程序运行了一段时间并有机会分割地址空间(与 RAM 无关)后,分配 90 MB 很容易失败。早在程序真正内存不足之前,就没有留下足够大的孔来容纳分配。否则,通过允许您的程序作为 64 位进程运行,在 C# 中可以轻松解决的问题。

标签: c# zip base64 encode


【解决方案1】:

不要试图把整件事都放在一块。

循环遍历 FileStream 中的字节。抓取三个字节的倍数并对它们进行编码。请务必使用 StringBuilder 来构建您的输出。

这将大大减少内存使用量。

【讨论】:

    【解决方案2】:

    [注意:此答案假定您可以分块处理最终的 base 64 字符串,例如通过将每个块依次写入某种流。]

    如果您编写一个辅助方法来读取最大大小的byte[] 块中的文件,这会简化,例如:

    public static IEnumerable<byte[]> ReadFileInBlocks(string filename, int blockSize)
    {
        byte[] buffer = new byte[blockSize];
    
        using (var file = File.OpenRead(filename))
        {
            while (true)
            {
                int n = file.Read(buffer, 0, buffer.Length);
    
                if (n == buffer.Length)
                {
                    yield return buffer;
                }
                else if (n > 0) // Must be the last block in the file (because n != buffer.Length)
                {
                    Array.Resize(ref buffer, n);
                    yield return buffer;         // Just this last block to return,
                    break;                       // and then we're done.
                }
                else // Exactly read to end of file in previous read, so we're already done.
                {
                    break;
                }
            }
        }
    }
    

    然后你可以编写一个简单的方法,从文件中依次返回从每个字节块转换而来的base 64字符串序列:

    public static IEnumerable<string> ToBase64Strings(string filename, int blockSize)
    {
        return ReadFileInBlocks(filename, blockSize).Select(Convert.ToBase64String);
    }
    

    然后假设您有办法处理每个转换后的 base-64 字符串块,请执行以下操作:

    foreach (var base64String in ToBase64Strings(myFilename, 1024))
        process(base64String);
    

    或者,您可以跳过中间 ReadFileInBlocks() 方法并将转换为 base 64 字符串折叠到其中,如下所示:

    public IEnumerable<string> ConvertToBase64StringInBlocks(string filename, int blockSize)
    {
        byte[] buffer = new byte[blockSize];
    
        using (var file = File.OpenRead(filename))
        {
            while (true)
            {
                int n = file.Read(buffer, 0, buffer.Length);
    
                if (n == 0) // Exactly read to end of file in previous read, so we're already done.
                {
                    break;
                }
                else
                {
                    yield return Convert.ToBase64String(buffer, 0, n);
                }
            }
        }
    }
    

    【讨论】:

    • Matthew Watson,我如何将 Base64 字符串解码为 zip 文件?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    • 2019-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多