【问题标题】:Calculate the size to a Base 64 encoded message计算 Base 64 编码消息的大小
【发布时间】:2010-12-04 17:21:24
【问题描述】:

我有一个二进制字符串,我用 Base 64 编码。现在,我需要事先知道最终 Base 64 编码字符串的大小。

有什么方法可以计算吗?

类似:

BinaryStringSize 为 64Kb 编码后 EncodedBinaryStringSize 为 127Kb。

哦,代码是 C 语言的。

谢谢。

【问题讨论】:

    标签: c base64


    【解决方案1】:
     if (inputSize == 0) return 0;
    
     int size = ((inputSize - 1) / 3) * 4 + 4;
     int nlines = (size - 1)/ maxLine + 1;
     return size + nlines * 2;
    

    当且仅当最后一行不完全符合最大行长度时,此公式才会添加终止 CRLF(MIME,rfc2045)。

    【讨论】:

      【解决方案2】:

      我认为这个公式应该有效:

      b64len = (size * 8 + 5) / 6
      

      【讨论】:

        【解决方案3】:

        我在 python 中遇到了类似的情况,使用 codecs.iterencode(text, "base64") 正确的计算是:

        adjustment = 3 - (input_size % 3) if (input_size % 3) else 0
        code_padded_size = ( (input_size + adjustment) / 3) * 4
        newline_size = ((code_padded_size) / 76) * 1
        return code_padded_size + newline_size
        

        【讨论】:

          【解决方案4】:

          这是一个简单的 C 实现(没有模数和三元运算符),用于原始 base64 编码大小(使用标准 '=' 填充):

          int output_size;
          output_size = ((input_size - 1) / 3) * 4 + 4;
          

          为此,如果需要,您将需要为 CRLF 添加任何额外开销。标准 base64 编码(RFC 3548 或 RFC 4648)允许 CRLF 换行符(64 或 76 个字符),但不需要它。 MIME 变体 (RFC 2045) 要求每 76 个字符后换行。

          例如,使用 76 个字符行构建的总编码长度:

          int final_size;
          final_size = output_size + (output_size / 76) * 2;
          

          查看base64 wikipedia entry 了解更多变体。

          【讨论】:

            【解决方案5】:

            geocar 的答案很接近,但有时可能会略有偏差。

            每输入 3 个字节就有 4 个字节输出。如果输入大小不是三的倍数,我们必须相加使其为一。否则别管它。

            input_size + ( (input_size % 3) ? (3 - (input_size % 3)) : 0) 
            

            将其除以 3,然后乘以 4。这是我们的总输出大小,包括填充。

            code_padded_size = ((input_size + ( (input_size % 3) ? (3 - (input_size % 3)) : 0) ) / 3) * 4
            

            正如我在评论中所说,总大小必须在加倍之前除以线宽,以正确考虑最后一行。否则 CRLF 字符的数量将被高估。我还假设如果该行是 72 个字符,则只会有一个 CRLF 对。这包括最后一行,但如果少于 72 个字符则不包括在内。

            newline_size = ((code_padded_size) / 72) * 2
            

            所以把它们放在一起:

            unsigned int code_padded_size = ((input_size + ( (input_size % 3) ? (3 - (input_size % 3)) : 0) ) / 3) * 4;
            unsigned int newline_size = ((code_padded_size) / 72) * 2;
            
            unsigned int total_size = code_padded_size + newline_size;
            

            或者让它更具可读性:

            unsigned int adjustment = ( (input_size % 3) ? (3 - (input_size % 3)) : 0);
            unsigned int code_padded_size = ( (input_size + adjustment) / 3) * 4;
            unsigned int newline_size = ((code_padded_size) / 72) * 2;
            
            unsigned int total_size = code_padded_size + newline_size;
            

            【讨论】:

            • 真的很好!顺便说一句,CRLF 不是 76 个字符,而不是 72 个字符吗? (根据本 RFC:tools.ietf.org/html/rfc4648
            • 行长可以是任意的,尽管 76 限制确实在那个 RFC 中。在这里使用 72 只是因为这是我继承的代码中使用的。
            【解决方案6】:

            查看b64 library。如果您传递NULL,函数b64_encode2() 可以给出所需大小的最大估计值,因此您可以确定地分配内存,然后再次调用传递缓冲区并让它进行转换。

            【讨论】:

              【解决方案7】:

              如果你使用 Base64 exactly right,包括用 = 字符填充结尾,然后每 72 个字符用 CR LF 将其拆分,则可以通过以下方式找到答案:

              code_size    = ((input_size * 4) / 3);
              padding_size = (input_size % 3) ? (3 - (input_size % 3)) : 0;
              crlfs_size   = 2 + (2 * (code_size + padding_size) / 72);
              total_size   = code_size + padding_size + crlfs_size;
              

              在 C 中,您也可以以 \0-byte 终止,因此那里会有一个额外的字节,并且您可能希望在编写每个代码的末尾时检查它们的长度,所以如果您'只是在寻找传递给malloc() 的内容,您实际上可能更喜欢浪费几个字节的版本,以使编码更简单:

              output_size = ((input_size * 4) / 3) + (input_size / 96) + 6;
              

              【讨论】:

              • CRLF-per-72 字符不是原始 Base 64 编码;它只是一个常见的变体。
              • 如果我在“and you break it with ...”中强调“and”,会更清楚吗?
              • 这个CRLF计算应该是:crlfs_size = 2 + (2 * ((code_size + padding_size) / 72));总大小必须在加倍之前除以线宽,以正确考虑最后一行。否则 CRLF 字符的数量将被高估。如果没有最终的 CRLF 对,也可能不需要 2 +。
              • 另外,我注意到 code_size 计算本身有一些缺陷。请参阅我的答案以获得经过充分测试的替代方案。
              • CRLF 不是 76 个字符,而不是 72 个字符吗? tools.ietf.org/html/rfc4648
              【解决方案8】:

              符合 MIME 的 base64 编码二进制数据的实际长度通常约为原始数据长度的 137%,但对于非常短的消息,由于标头的开销,开销可能会高得多。非常粗略地说,base64 编码的二进制数据的最终大小等于原始数据大小的 1.37 倍 + 814 字节(对于标头)。

              换句话说,你可以用这个公式来近似解码数据的大小:

              BytesNeededForEncoding = (string_length(base_string) * 1.37) + 814;
              BytesNeededForDecoding = (string_length(encoded_string) - 814) / 1.37;
              

              来源:http://en.wikipedia.org/wiki/Base64

              【讨论】:

              • 这仅适用于 MIME 编码的消息,不一定是未经修饰的 Base64。
              【解决方案9】:

              Base 64 将 3 个字节转换为 4 个字节。

              如果你的一组位碰巧不是 24 位的倍数,则必须将其填充为 24 位的倍数(3 个字节)。

              【讨论】:

              • 因此,length(Base-64) = 4 * (length(Binary) + 2) / 3。然后可能需要考虑换行符和尾随 null。
              • @Jonathan Leffler:正确。如果是 MIME 附件,则需要考虑所有 MIME 开销。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-04-03
              • 1970-01-01
              • 2014-11-30
              • 1970-01-01
              • 2011-10-11
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多