在阅读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),这取决于是否需要一个结束换行符。
其他回答
4 * n / 3为无填充长度。
并四舍五入到最接近4的倍数进行填充,因为4是2的幂,可以使用逐位逻辑运算。
((4 * n / 3) + 3) & ~3
在我看来,正确的公式应该是:
n64 = 4 * (n / 3) + (n % 3 != 0 ? 4 : 0)
对于所有会说C语言的人,看看这两个宏:
// calculate the size of 'output' buffer required for a 'input' buffer of length x during Base64 encoding operation
#define B64ENCODE_OUT_SAFESIZE(x) ((((x) + 3 - 1)/3) * 4 + 1)
// calculate the size of 'output' buffer required for a 'input' buffer of length x during Base64 decoding operation
#define B64DECODE_OUT_SAFESIZE(x) (((x)*3)/4)
从这里拍的。
(试图给出一个简洁而完整的推导。)
每个输入字节有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),这取决于是否需要一个结束换行符。
简单的javascript实现
function sizeOfBase64String(base64String) {
if (!base64String) return 0;
const padding = (base64String.match(/(=*)$/) || [])[1].length;
return 4 * Math.ceil((base64String.length / 3)) - padding;
}