【发布时间】:2010-12-04 17:21:24
【问题描述】:
我有一个二进制字符串,我用 Base 64 编码。现在,我需要事先知道最终 Base 64 编码字符串的大小。
有什么方法可以计算吗?
类似:
BinaryStringSize 为 64Kb 编码后 EncodedBinaryStringSize 为 127Kb。
哦,代码是 C 语言的。
谢谢。
【问题讨论】:
我有一个二进制字符串,我用 Base 64 编码。现在,我需要事先知道最终 Base 64 编码字符串的大小。
有什么方法可以计算吗?
类似:
BinaryStringSize 为 64Kb 编码后 EncodedBinaryStringSize 为 127Kb。
哦,代码是 C 语言的。
谢谢。
【问题讨论】:
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)。
【讨论】:
我认为这个公式应该有效:
b64len = (size * 8 + 5) / 6
【讨论】:
我在 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
【讨论】:
这是一个简单的 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 了解更多变体。
【讨论】:
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;
【讨论】:
查看b64 library。如果您传递NULL,函数b64_encode2() 可以给出所需大小的最大估计值,因此您可以确定地分配内存,然后再次调用传递缓冲区并让它进行转换。
【讨论】:
如果你使用 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;
【讨论】:
符合 MIME 的 base64 编码二进制数据的实际长度通常约为原始数据长度的 137%,但对于非常短的消息,由于标头的开销,开销可能会高得多。非常粗略地说,base64 编码的二进制数据的最终大小等于原始数据大小的 1.37 倍 + 814 字节(对于标头)。
换句话说,你可以用这个公式来近似解码数据的大小:
BytesNeededForEncoding = (string_length(base_string) * 1.37) + 814;
BytesNeededForDecoding = (string_length(encoded_string) - 814) / 1.37;
【讨论】:
Base 64 将 3 个字节转换为 4 个字节。
如果你的一组位碰巧不是 24 位的倍数,则必须将其填充为 24 位的倍数(3 个字节)。
【讨论】: