Pau*_*l R 186
每个字符用于表示6位(log2(64) = 6
).
因此,使用4个字符来表示4 * 6 = 24 bits = 3 bytes
.
所以你需要4*(n/3)
字符来表示n
字节,这需要四舍五入到4的倍数.
由四舍五入到4的倍数产生的未使用的填充字符的数量显然将是0,1,2或3.
小智 51
4 * n / 3
给出了无衬垫的长度.
并且向上舍入到最接近的4的倍数用于填充,并且4是2的幂可以使用按位逻辑运算.
((4 * n / 3) + 3) & ~3
Run Code Online (Sandbox Code Playgroud)
Dav*_*rtz 25
作为参考,Base64编码器的长度公式如下:
如上所述,给定n
字节数据的Base64编码器将产生一串4n/3
Base64字符.换句话说,每3个字节的数据将产生4个Base64字符.编辑:评论正确指出我以前的图形没有考虑填充; 正确的公式是 Ceiling(4n/3)
.
Wikipedia文章准确显示了ASCII Man
字符串TWFu
在其示例中如何编码为Base64字符串.输入字符串的大小为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个字符长,正如我们的预期.
通常我们不想使用双精度因为我们不想使用浮点运算,舍入误差等.它们不是必需的.
为此,最好记住如何执行上限划分: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));
}
}
Run Code Online (Sandbox Code Playgroud)
加厚
我们知道每3个字节(或更少)我们需要4个字符的块.那么公式变为(对于x = n和y = 3):
blocks = (bytes + 3 - 1) / 3
chars = blocks * 4
Run Code Online (Sandbox Code Playgroud)
或合并:
chars = ((bytes + 3 - 1) / 3) * 4
Run Code Online (Sandbox Code Playgroud)
你的编译器会优化掉3 - 1
,所以只需保留它就可以保持可读性.
不用护垫
不常见的是unpadded变体,为此我们记得每个我们需要每个6位的字符,四舍五入:
bits = bytes * 8
chars = (bits + 6 - 1) / 6
Run Code Online (Sandbox Code Playgroud)
或合并:
chars = (bytes * 8 + 6 - 1) / 6
Run Code Online (Sandbox Code Playgroud)
然而,我们仍然可以除以2(如果我们愿意):
chars = (bytes * 4 + 3 - 1) / 3
Run Code Online (Sandbox Code Playgroud)
如果您不相信您的编译器为您做最后的优化(或者如果您想混淆您的同事):
加厚
((n + 2) / 3) << 2
Run Code Online (Sandbox Code Playgroud)
不用护垫
((n << 2) | 2) / 3
Run Code Online (Sandbox Code Playgroud)
所以我们有两种逻辑计算方法,我们不需要任何分支,位操作或模运算 - 除非我们真的想要.
笔记:
(试图给出一个简洁而完整的推导。)
每个输入字节有 8 位,因此对于n 个输入字节,我们得到:
n × 8 输入位
每 6 位是一个输出字节,因此:
ceil ( n × 8 / 6) = ceil ( n × 4 / 3) 输出字节
这是没有填充。
通过填充,我们将其四舍五入为四的倍数输出字节:
ceil ( ceil ( n × 4 / 3) / 4) × 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
Run Code Online (Sandbox Code Playgroud)
最后,在 MIME Base64 编码的情况下,每 76 个输出字节需要两个额外的字节 (CR LF),根据是否需要终止换行符向上或向下舍入。
小智 5
我认为给定的答案忽略了原始问题的重点,即需要分配多少空间来适应给定长度为n字节的二进制字符串的base64编码.
答案是 (floor(n / 3) + 1) * 4 + 1
这包括填充和终止空字符.如果要进行整数运算,则可能不需要发言权.
包括填充,base64字符串需要四个字节用于原始字符串的每个三字节块,包括任何部分块.当添加填充时,字符串末尾的额外一个或两个字节仍将转换为base64字符串中的四个字节.除非您有非常具体的用途,否则最好添加填充,通常是等号.我在C中为空字符添加了一个额外的字节,因为没有它的ASCII字符串有点危险,你需要单独携带字符串长度.
小智 5
这是一个函数,用于将编码的Base 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;
}
Run Code Online (Sandbox Code Playgroud)
对于所有讲 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)
Run Code Online (Sandbox Code Playgroud)
取自这里。
归档时间: |
|
查看次数: |
153277 次 |
最近记录: |