在阅读base64维基之后…

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

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

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

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

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

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

问题:

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


当前回答

作为参考,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个字符长。

其他回答

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

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

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

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

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

我在其他回答中没有看到简化的公式。逻辑是覆盖的,但我想要一个最基本的形式为我的嵌入式使用:

  Unpadded = ((4 * n) + 2) / 3

  Padded = 4 * ((n + 2) / 3)

注意:当计算无填充计数时,我们四舍五入整数除法,即加上除数-1,在这种情况下是+2

对于所有会说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) 

从这里拍的。

如果有人有兴趣在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
}