📜  将ASCII字符串编码为Base-64格式

📅  最后修改于: 2021-05-25 21:47:17             🧑  作者: Mango

Base 64是一种将二进制数据转换为文本格式的编码方案,以便可以在不损坏数据的情况下轻松地在网络上传输编码后的文本数据。 Base64通常用于许多应用程序中,包括通过MIME的电子邮件以及以XML存储复杂数据。
将正常的二进制数据发送到网络的问题在于,底层协议可能会误解位,在接收节点上产生不正确的数据,这就是我们使用此代码的原因。

为什么以64为底?

在对数据进行编码后,结果文本具有在许多字符集中广泛存在的那些字符,因此,数据被破坏或修改的可能性很小。

如何转换为base 64格式?

在base64中设置的字符是

char_set = "ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz0123456789+/" 
// 64 characters

基本思路

让我们举个例子。我们必须将字符串“ MENON”编码为base64格式。让我们将“ MENON”称为input_str ,将base64字符集(“ ABC .. + /”)上方的字符称为char_set,并将结果编码后的字符串称为res_str

  1. input_str中取3个字符,即“ MEN”,因为每个字符的大小为8位,我们将拥有(8 * 3)24位。
  2. 将它们分组为每个6位的块(24/6 = 4个块)。 (为什么是6?)因为2 ^ 6 = 64个字符,所以我们可以用6位来表示char_set中的每个字符。
  3. 将每个6位的块转换为其相应的十进制值。获得的十进制值是char_set中所得编码字符的索引。
  4. 因此,对于input_str中的每3个字符,我们将在res_str中接收4个字符。
  5. 如果在input_str中剩下少于3个字符(即“ ON”),该怎么办。我们有16位,块将是16/6 = 2个块。最右边的4位将不构成适当的块(1个块= 6位),因此我们在块的右侧附加零以使其成为适当的块,即在右边附加2个零。现在我们有3个适当的块,找到每个块的对应十进制值以获得索引。
  6. 由于input_str中的字符少于3个(“ ON”),我们将在res_str中附加“ =”。例如,在res_str中, “ ON”在此处3 – 2 = 1填充“ =”。

例子

1.将“ MENON”转换为其(8位)二进制状态格式。取字符串的每个字符并编写其8位二进制表示形式。
字符串中要编码的字符的ASCII值

M : 77 (01001101), E : 69 (01000101), 
N : 78 (01001110), O : 79 (01001111), N : 78 (01001110)

以上字符串的结果二进制数据为:

01001101 01000101 01001110 01001111 01001110

2.从左侧的6位make块开始,直到覆盖所有位
位流:

(010011) (010100) (010101) (001110) (010011) (110100) (1110)

3.如果最右边的块小于6位,则在该块的右边附加零以使其成为6位。在上面的示例中,我们必须附加2个零使其变为6。
位流:

(010011) (010100) (010101) (001110) (010011) (110100) (111000)

注意粗体零。

4.从input_str(“ MEN”)中取3个字符,即24位,并找到相应的十进制值(char_set的索引)。
方块:

INDEX --> (010011) : 19, (010100) : 20, (010101) : 21, (001110) : 14
char_set[19] = T, char_set[20] = U, char_set[21] = V, char_set[14] = O

因此,我们的input_str =“ MEN”将被转换为编码字符串“ TUVO”。

5.取剩余的字符(“ ON”)。我们必须用1“ =”填充结果编码的字符串,因为input_str中的字符数少于3。 (3 – 2 = 1个填充)
方块:

INDEX --> (010011) : 19 (110100) : 52 (111000) : 56
char_set[19] = T char_set[52] = 0 char_set[21] = 4
So our input_str = "ON" will be converted to encoded string "T04=".

例子:

Input : MENON // string in ASCII
Output :TUVOT04= // encoded string in Base 64.

Input : geeksforgeeks
Output : Z2Vla3Nmb3JnZWVrcw==
方法

我们可以使用按位运算运算符对字符串进行编码。我们可以取一个整数“ val”(在大多数编译器中通常为4个字节),并将input_str的所有字符(一次3个)存储在val中。 input_str中的字符将存储在val中
以位的形式。我们将使用(OR运算符)存储字符,将(LEFT – SHIFT)乘以8,以便
为另外8位腾出空间。以类似的方式,我们将使用(RIGHT-SHIFT)一次从val 6中检索位。
并通过&与63(111111)进行运算来找到位的值,这将为我们提供索引。然后,我们只需要转到char_set的索引就可以得到结果字符。

// C program to encode an ASCII 
// string in Base64 format
#include 
#include 
#define SIZE 1000
  
// Takes string to be encoded as input
// and its length and returns encoded string
char* base64Encoder(char input_str[], int len_str)
{
    // Character set of base64 encoding scheme
    char char_set[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      
    // Resultant string
    char *res_str = (char *) malloc(SIZE * sizeof(char));
      
    int index, no_of_bits = 0, padding = 0, val = 0, count = 0, temp;
    int i, j, k = 0;
      
    // Loop takes 3 characters at a time from 
    // input_str and stores it in val
    for (i = 0; i < len_str; i += 3)
        {
            val = 0, count = 0, no_of_bits = 0;
  
            for (j = i; j < len_str && j <= i + 2; j++)
            {
                // binary data of input_str is stored in val
                val = val << 8; 
                  
                // (A + 0 = A) stores character in val
                val = val | input_str[j]; 
                  
                // calculates how many time loop 
                // ran if "MEN" -> 3 otherwise "ON" -> 2
                count++;
              
            }
  
            no_of_bits = count * 8; 
  
            // calculates how many "=" to append after res_str.
            padding = no_of_bits % 3; 
  
            // extracts all bits from val (6 at a time) 
            // and find the value of each block
            while (no_of_bits != 0) 
            {
                // retrieve the value of each block
                if (no_of_bits >= 6)
                {
                    temp = no_of_bits - 6;
                      
                    // binary of 63 is (111111) f
                    index = (val >> temp) & 63; 
                    no_of_bits -= 6;         
                }
                else
                {
                    temp = 6 - no_of_bits;
                      
                    // append zeros to right if bits are less than 6
                    index = (val << temp) & 63; 
                    no_of_bits = 0;
                }
                res_str[k++] = char_set[index];
            }
    }
  
    // padding is done here
    for (i = 1; i <= padding; i++) 
    {
        res_str[k++] = '=';
    }
  
    res_str[k] = '\0;';
  
    return res_str;
  
}
  
  
// Driver code
int main()
{
    char input_str[] = "MENON";
    int len_str;
  
    // calculates length of string
    len_str = sizeof(input_str) / sizeof(input_str[0]);
      
    // to exclude '\0' character
    len_str -= 1; 
  
    printf("Input string is : %s\n", input_str);
    printf("Encoded string is : %s\n", base64Encoder(input_str, len_str));
    return 0;
}

输出:

Input string is : MENON
Encoded string is : TUVO04=

时间复杂度: O(2 * N)将位插入val +从val检索位

练习:实现base 64解码器

想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。