在阅读base64维基之后…
我想知道这个公式是怎么运作的
给定一个长度为n的字符串,base64的长度为
即:4*Math.Ceiling(((double)s.Length/3)))
我已经知道base64的长度必须是%4==0,以允许解码器知道原始文本的长度。
序列的最大填充数可以是=或==。
wiki:每个输入字节的输出字节数大约是4 / 3 (33%) 开销)
问题:
以上信息是如何与输出长度相匹配的?
在阅读base64维基之后…
我想知道这个公式是怎么运作的
给定一个长度为n的字符串,base64的长度为
即:4*Math.Ceiling(((double)s.Length/3)))
我已经知道base64的长度必须是%4==0,以允许解码器知道原始文本的长度。
序列的最大填充数可以是=或==。
wiki:每个输入字节的输出字节数大约是4 / 3 (33%) 开销)
问题:
以上信息是如何与输出长度相匹配的?
当前回答
(试图给出一个简洁而完整的推导。)
每个输入字节有8位,所以对于n个输入字节,我们得到:
N × 8输入位
每6位是一个输出字节,因此:
ceil (n - 6) = ceil (n×8×4 - 3 ) 输出字节
这是没有填充的。
对于填充,我们四舍五入为四个输出字节中的多个:
ceil (ceil (n×4 / 3))×4 = ceil (n×4 / 3 - 4)×4 = ceil (n - 3)×4字节输出
见嵌套划分(维基百科)的第一个等价。
使用整数算术,ceil(n / m)可以计算为(n + m - 1) div m, 因此我们得到:
(n * 4 + 2) div 3没有填充 (n + 2) div 3 * 4与填充
说明:
n with padding (n + 2) div 3 * 4 without padding (n * 4 + 2) div 3
------------------------------------------------------------------------------
0 0 0
1 AA== 4 AA 2
2 AAA= 4 AAA 3
3 AAAA 4 AAAA 4
4 AAAAAA== 8 AAAAAA 6
5 AAAAAAA= 8 AAAAAAA 7
6 AAAAAAAA 8 AAAAAAAA 8
7 AAAAAAAAAA== 12 AAAAAAAAAA 10
8 AAAAAAAAAAA= 12 AAAAAAAAAAA 11
9 AAAAAAAAAAAA 12 AAAAAAAAAAAA 12
10 AAAAAAAAAAAAAA== 16 AAAAAAAAAAAAAA 14
11 AAAAAAAAAAAAAAA= 16 AAAAAAAAAAAAAAA 15
12 AAAAAAAAAAAAAAAA 16 AAAAAAAAAAAAAAAA 16
最后,在MIME Base64编码的情况下,每76个输出字节需要两个额外的字节(CR LF),这取决于是否需要一个结束换行符。
其他回答
每个字符代表6位(log2(64) = 6)。
因此用4个字符表示4 * 6 = 24位= 3个字节。
所以你需要4*(n/3)个字符来表示n个字节,这需要四舍五入到4的倍数。
由于四舍五入到4的倍数而导致的未使用填充字符的数量显然是0、1、2或3。
作为参考,Base64编码器的长度公式如下:
正如你所说的,给定n个字节的数据,一个Base64编码器将产生一个4n/3个Base64字符的字符串。换句话说,每3个字节的数据将导致4个Base64字符。编辑:一个评论正确地指出,我之前的图形没有说明填充;正确的填充公式是4(Ceiling(n/3))。
维基百科的文章在示例中准确地展示了ASCII字符串Man如何编码为Base64字符串TWFu。输入字符串的大小是3字节,或24位,因此公式正确地预测输出将是4字节(或32位)长:TWFu。该过程将每6位数据编码为64个Base64字符中的一个,因此24位输入除以6得到4个Base64字符。
您在注释中询问编码123456的大小。请记住,该字符串的每个字符的大小都是1字节或8位(假设ASCII/UTF8编码),我们正在编码6字节或48位的数据。根据公式,我们期望输出长度为(6字节/ 3字节)* 4个字符= 8个字符。
将123456放入Base64编码器中创建MTIzNDU2,正如我们预期的那样,它有8个字符长。
如果n%3不为零,我相信这个是正确答案,不是吗?
(n + 3-n%3)
4 * ---------
3
Mathematica版本:
SizeB64[n_] := If[Mod[n, 3] == 0, 4 n/3, 4 (n + 3 - Mod[n, 3])/3]
玩得开心
GI
下面是一个函数来计算一个base64编码文件的原始大小为KB的字符串:
private Double calcBase64SizeInKBytes(String base64String) {
Double result = -1.0;
if(StringUtils.isNotEmpty(base64String)) {
Integer padding = 0;
if(base64String.endsWith("==")) {
padding = 2;
}
else {
if (base64String.endsWith("=")) padding = 1;
}
result = (Math.ceil(base64String.length() / 4) * 3 ) - padding;
}
return result / 1000;
}
我认为给出的答案忽略了原始问题的重点,即需要分配多少空间来适合长度为n字节的给定二进制字符串的base64编码。
答案是((n / 3) + 1) * 4 + 1
这包括填充和终止空字符。如果你在做整数运算,你可能不需要楼层调用。
Including padding, a base64 string requires four bytes for every three-byte chunk of the original string, including any partial chunks. One or two bytes extra at the end of the string will still get converted to four bytes in the base64 string when padding is added. Unless you have a very specific use, it is best to add the padding, usually an equals character. I added an extra byte for a null character in C, because ASCII strings without this are a little dangerous and you'd need to carry the string length separately.