Base64编码长度计算?(Base64 length calculation?)

2019-06-21 03:33发布

阅读中的Base64后维基 ...

我试图找出如何公式如下工作:

鉴于一长度的字符串n ,以base64长度将

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

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

填充的一个序列的最大数量可以是===

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

题:

如何上面的信息与输出长度定居

Answer 1:

每个字符被用来表示6位( log2(64) = 6 )。

因此4个字符被用来表示4 * 6 = 24 bits = 3 bytes

因此,你需要4*(n/3)个字符来表示n字节,这需要四舍五入为4的倍数。

从上舍入的4的倍数所得的未使用的填充字符的数量显然会0,1,2或3。



Answer 2:

4 * n / 3给出了未填充的长度。

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

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


Answer 3:

作为参考,Base64的编码器的长度公式如下:

如你所说,一个Base64编码器给定的n的数据的字节将产生的串4n/3的Base64字符。 换句话说,每3个字节的数据将导致4点Base64编码的字符。 编辑注释正确地指出,我以前的图形没有考虑填充; 正确的公式是 Ceiling(4n/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 bytes / 3 bytes) * 4 characters = 8 characters

123456为Base64编码器创建MTIzNDU2 ,这是8个字符长,正如我们的预期。



Answer 4:

整型

一般来说,我们不希望用双打,因为我们不希望使用浮点OPS,舍入误差等,他们只是没有必要的。

为此,它是一个好主意,记得如何执行天花板师: ceil(x / y)在双打可以写为(x + y - 1) / y (同时避免负数,但溢出小心)。

可读

如果你去了可读性,你当然也喜欢看这个节目它(在Java中例如,C:你可以使用宏的,当然):

public static int ceilDiv(int x, int y) {
    return (x + y - 1) / y;
}

public static int paddedBase64(int n) {
    int blocks = ceilDiv(n, 3);
    return blocks * 4;
}

public static int unpaddedBase64(int n) {
    int bits = 8 * n;
    return ceilDiv(bits, 6);
}

// test only
public static void main(String[] args) {
    for (int n = 0; n < 21; n++) {
        System.out.println("Base 64 padded: " + paddedBase64(n));
        System.out.println("Base 64 unpadded: " + unpaddedBase64(n));
    }
}

内联

加厚

我们知道,我们需要4个字符块的时候,每次3个字节(或更少)。 所以,则公式变成(对于x = n和y = 3):

blocks = (bytes + 3 - 1) / 3
chars = blocks * 4

或组合:

chars = ((bytes + 3 - 1) / 3) * 4

你的编译器将优化了3 - 1 ,那么就让它这样保持可读性。

不用护垫

较少见的是未填充变形,为此,我们记得每次我们需要为每个6位字符,围捕:

bits = bytes * 8
chars = (bits + 6 - 1) / 6

或组合:

chars = (bytes * 8 + 6 - 1) / 6

我们可以然而仍然除以二(如果我们想):

chars = (bytes * 4 + 3 - 1) / 3

不可读

如果你不信任你的编译器做最后的优化,你(或者,如果你想混淆你的同事):

加厚

((n + 2) / 3) << 2

不用护垫

((n << 2) | 2) / 3

就这样,我们是,计算的两个逻辑方式,而我们不需要任何分支机构,位OP或模OPS - 除非我们真的想。

笔记:

  • 很显然,你可能需要加1的计算,包括空终止字节。
  • 对于MIME,你可能需要采取的可能行结束符等(找其他答案为)照顾。


Answer 5:

我认为给出的答案错过了原来的问题,这是需要多大的空间分配给符合base64编码为长度为n个字节给定的二进制字符串的地步。

答案是(floor(n / 3) + 1) * 4 + 1

这包括填充和终止空字符。 如果你正在做的整数运算,你可能不需要楼层呼叫。

包括填充,一个base64串需要四个字节的原始字符串的每三个字节块,包括任何局部块。 添加填充时,在字符串的结尾额外的一个或两个字节仍然会得到转化为四个字节的字符串的base64。 除非你有一个非常具体的用途,最好是添加填料,通常是等于字符。 我增加了一个额外的字节在C空字符,因为如果没有这个ASCII字符串是有点危险的,你需要分别进行字符串的长度。



Answer 6:

这里是计算的编码基本64文件作为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;
}


Answer 7:

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

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


Answer 8:

当人人都在讨论代数公式,我宁愿只使用BASE64本身告诉我:

$ echo "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."| wc -c

525

$ echo "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." | base64 | wc -c

710

因此,似乎的3个字节的通过式4个的base64字符所代表似乎是正确的。



Answer 9:

在窗口 - 我想估计mime64大小的缓冲区的大小,但所有精确的计算公式的并没有为我工作 - 我终于已经结束了,像这样的近似公式:

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

因此,上+1 - 它用于ASCII零 - 最后一个字符需要分配给存储零的结局 - 但为什么“二进制缓存大小”为+ 1 - 我怀疑有一些mime64终止字符? 或者可能这是一些对齐问题。



Answer 10:

在JavaScript简单implementantion

function sizeOfBase64String(base64String) {
    if (!base64String) return 0;
    const padding = (base64String.match(/(=*)$/) || [])[1].length;
    return 4 * Math.ceil((base64String.length / 3)) - padding;
}


Answer 11:

如果有感兴趣的人在实现JS的@Pedro席尔瓦的解决方案,我只是移植了它此相同的解决方案:

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
}


Answer 12:

我相信这个人是如果n%3不是零一个确切的答案,不是吗?

    (n + 3-n%3)
4 * ---------
       3

数学版:

SizeB64[n_] := If[Mod[n, 3] == 0, 4 n/3, 4 (n + 3 - Mod[n, 3])/3]

玩得开心

GI



文章来源: Base64 length calculation?