base64的解码表构造

时间:2012-07-19 10:49:14

标签: c base64

我正在阅读这个libb64源代码,用于编码和解码base64数据。

我知道编码过程,但我无法弄清楚如何构造以下解码表以便快速查找以执行编码的base64字符的解码。这是他们正在使用的表格:

static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};

有人可以解释一下这个表中的值如何用于解码目的。

3 个答案:

答案 0 :(得分:5)

这是一个移位且有限的ASCII翻译表。表的键是ASCII值,值是base64解码值。该表被移位,使得索引0实际映射到ASCII字符+,并且任何其他索引在+之后映射ASCII值。表中的第一个条目ASCII字符+映射到base64值62。然后忽略三个字符(ASCII ,-.),并将下一个字符映射到base64值63。下一个字符是ASCII /

如果您查看该表和ASCII table

,其余部分将变得明显

它的用法是这样的:

int decode_base64(char ch) {
    if (ch < `+` or ch > `z`) {
        return SOME_INVALID_CH_ERROR;
    }

    /* shift range into decoding table range */
    ch -= `+`;

    int base64_val = decoding[ch];

    if (base64_val < 0) {
        return SOME_INVALID_CH_ERROR;
    }

    return base64_val;
}

答案 1 :(得分:5)

众所周知,每个字节有8位,可能有256个组合,带有2个符号(base2) 使用2个符号需要浪费8个字符来表示一个字节,例如'01010011' 使用base 64可以表示64个组合,其中包含1个char ...
所以,我们有一个基表:
   A = 000000
   B = 000001
   C = 000010
   ...
如果您有单词'Man',那么您有字节:
 01001101,01100001,01101110
所以流:
 011010110000101101110

中断六位组:010011 010110 000101 101110
   010011 = T
   010110 = W
   000101 = F
   101110 = u
所以,'男人'=&gt; base64编码='TWFu'。
如图所示,这对于长度为6的长度的流是完美的

如果您的流不是6的倍数,例如'Ma',您就拥有了流:
 010011 010110 0001
你需要完成6人组:  010011 010110 000100
所以你有编码基数64:
   010011 = T
   010110 = W
   000100 = E
所以,'Ma'=&gt; 'TWE'

在解码流之后,在这种情况下,您需要将最后一个多个长度计算为8的倍数,因此删除额外的位以获取原始流:
   T = 010011
   W = 010110
   E = 000100
1)010011 010110 000100
2)01001101 01100001 00
3)01001101 01100001 ='Ma'
实际上,当我们设置尾随的00时,我们用'='标记Base64字符串的结尾到每个尾随'00添加('Ma'==&gt; Base64'TWE =')


另见链接:http://www.base64decode.org/


在基础64上表示的图像是用许多应用程序中的字符串表示的好选项,其中难以直接使用真实二进制流。真正的二进制流更好,因为它是一个base256,但在HTML中很难,例如,有两种方式,轻微流量,或更容易使用字符串。

也参见ASCII码,base 64的字符在表ASCII上从范围'+'到'z'但是'+'和'z'之间有一些不是64位符号的值

   '+'= ASCII DEC 43
   ...
   'z'= ASCII DEC 122
   从DEC 43到122是80值但是    43 OK ='+'
   44不是基本64个符号,因此解码索引是-1(无效符号到base64)
   45 ....    46 ...
   ...
   122 OK ='z'
做解码所需的char,将43('+')递减为vector上的索引0,以便通过索引快速访问,解码[80] = {62,-1,-1 ........, 49,50,51};


   罗伯托诺瓦科斯基
   开发者系统

答案 2 :(得分:0)

考虑这两个映射表:

static const char decodingTab[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
static unsigned char encodingTab[64]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

decodingTab是encondingTab的反向映射表。 因此,decodingTab [i]永远不应为-1。 实际上,仅期望64个值。但是encodingTab的大小是128。 因此,在解码表中,意外索引值设置为-1(不在[0,63]中的任意数字)

char c;
unsigned char i;
...
encoding[decoding[c]]=c;
decoding[encoding[i]=i;

希望有帮助。