编码类似于Base64的字节数组,但具有任意基数

时间:2015-05-28 03:22:59

标签: c# algorithm encoding base64 decode

该过程是否有一个名称,您在其中获取8位字节流并将它们切片为存储在8位容器中的n位片段?

这个想法非常类似于Base64编码,你将1和0的流分成6位块(而不是8),这意味着每个块的十进制值都可以为0 - 63,每个都被赋予一个独特的人类可读字符。就我而言,我并不希望为每个块分配一个特定的角色。

例如,输入8位字节:

11100101 01101100 01010011 00001100 11000000 10111101

成为6位片段:

111001 010110 110001 010011 000011 001100 000010 111101

随后存储为:

00111001 00010110 00110001 00010011 00000011 00001100 00000010 00111101

或者,可选地,偏移量为1位:

01110010 00101100 01100010 00100110 00000110 00011000 00000100 01111010

或偏移2位:

11100100 01011000 11000100 01001100 00001100 00110000 00001000 11110100

我希望在C#中编写一个算法,将一个字节数组编码为任意长度的任意偏移量,另一个算法再将其转换回来。

经过相当多的头痛之后,我以为我已经成功编写了前向算法来编码一个字节数组。它适用于我的所有测试用例,但是当开始编写反向算法时,我意识到整个问题比我想象的要复杂得多,事实上,我的前向算法并不适用于n< 4。

我想用按位运算符编写算法,这是更合适和更优雅的解决方案。另一种方法是将字节数组转换为1和0的长字符串进行切片,但这样会慢得多。

这是我的前向算法,适用于n> = 4:

的情况
public static byte[] EncodeForward(byte[] input, int n, int offset = 0)
{
    byte[] output = new byte[(int)Math.Ceiling(input.Length * 8.0 / n)];

    output[0] = (byte)(input[0] >> (8 - n));

    int p = 1;
    int r = 8 - n;

    for (int i = 1; i < input.Length; i++)
    {
        output[p++] = (byte)((byte)((byte)(input[i - 1] << (8 - r)) | (byte)(input[i] >> r)) >> (8 - n - offset));

        if ((r += (8 - n)) == n)
        {
            output[p++] = (byte)(input[i] & (byte)(0xFF >> (8 - n)));
            r = 0;
        }
    }

    return output;
}

我最初只考虑n = 7的情况,因此每个输出字节将由最多7个输入字节的部分组成。然而,在n

我本人希望自己编写正向和反向算法,但老实说,经过这段时间调试和测试我所写的内容,现在发现这种方法对于n&lt; 4,我只是寻找有用的东西。这两个算法只是我正在研究的项目的一小部分。

这个编码/解码程序是否有名称,是否有内置的方法在C#中执行,或者是否有可以执行此操作的库?

1 个答案:

答案 0 :(得分:0)

你快到了。您只需要和中间16位缓冲区和未处理的位计数器。免责声明:我不知道C#。下面的(伪)代码是用C写的;你可能需要一些调整。

用于编码,

   uint16_t buffer = 0;
   int remaining = 16;
   while (i < input.Length) {
       while (remaining > 8) {
           buffer |= input[i++] << (remaining - width);
           remaining += width;
       }
       output[p++] = (buffer >> 8) & 0x00ff;
       buffer <<= 8;
       remaining += 8;
   }

用于解码:

#include "pokemon.h"

 int main()
{
    int choice;

    cout<<"input 1 2 or 3"<<endl;
    cin>>choice;

    if(choice==1||choice==2||choice==3)
    {
        pokemon(choice);
    }

}