在阅读base64维基之后…

我想知道这个公式是怎么运作的

给定一个长度为n的字符串,base64的长度为

即:4*Math.Ceiling(((double)s.Length/3)))

我已经知道base64的长度必须是%4==0,以允许解码器知道原始文本的长度。

序列的最大填充数可以是=或==。

wiki:每个输入字节的输出字节数大约是4 / 3 (33%) 开销)

问题:

以上信息是如何与输出长度相匹配的?


当前回答

4 * n / 3为无填充长度。

并四舍五入到最接近4的倍数进行填充,因为4是2的幂,可以使用逐位逻辑运算。

((4 * n / 3) + 3) & ~3

其他回答

在windows中-我想估计mime64大小的缓冲区的大小,但所有精确的计算公式都不适合我-最后我得到了这样的近似公式:

Mine64字符串分配大小(近似) =((4 *((二进制缓冲区大小)+ 1))/ 3)+ 1)

所以最后+1 -它用于ascii- 0 -最后一个字符需要分配来存储零结束-但为什么“二进制缓冲区大小”是+1 -我怀疑有一些mime64终止字符?或者这可能是一些对齐问题。

如果有人有兴趣在JS中实现@Pedro Silva解决方案,我只是为它移植了相同的解决方案:

const getBase64Size = (base64) => {
  let padding = base64.length
    ? getBase64Padding(base64)
    : 0
  return ((Math.ceil(base64.length / 4) * 3 ) - padding) / 1000
}

const getBase64Padding = (base64) => {
  return endsWith(base64, '==')
    ? 2
    : 1
}

const endsWith = (str, end) => {
  let charsFromEnd = end.length
  let extractedEnd = str.slice(-charsFromEnd)
  return extractedEnd === end
}

(试图给出一个简洁而完整的推导。)

每个输入字节有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。

在我看来,正确的公式应该是:

n64 = 4 * (n / 3) + (n % 3 != 0 ? 4 : 0)