一个有效的方式为Base64 EN $ C C的字节数组$?数组、字节、有效、方式

2023-09-02 21:36:55 作者:少年亦凉心凉意。

我有一个字节[] 和我正在寻找为Base64 EN $ C C $它最有效的方式。

I have a byte[] and I'm looking for the most efficient way to base64 encode it.

问题是,内置的.NET方法 Convert.FromBase64CharArray 要求的char [] 作为输入和转换我的字节[] 的char [] 只是为了再次转换到Base64 EN codeD阵似乎pretty的愚蠢。

The problem is that the built in .Net method Convert.FromBase64CharArray requires a char[] as an input, and converting my byte[] to a char[] just to convert it again to a base64 encoded array seems pretty stupid.

有没有更直接的方式做到这一点?

Is there any more direct way to do it?

我会expaling我想要获得了这幅更好 - 我有一个字节[],我需要返回一个新的base64恩codeD 字节[]

[] I'll expaling what I want to acheive better - I have a byte[] and I need to return a new base64 encoded byte[]

推荐答案

下面是code为Base64 EN code直接把字节数组(测试将执行.NET实现±10%,但分配一半的内存):

Here is the code to base64 encode directly to byte array (tested to be performing +-10% of .Net Implementation, but allocates half the memory):

static byte[] base64EncodingTable = 
      Encoding.ASCII.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij"
                             +"klmnopqrstuvwxyz0123456789+/");

public byte[] appendBase64( byte[] data
                          , int offset
                          , int size
                          , bool addLineBreaks = false ) 
    {
        byte[] buffer;
        int requiredSize = (4 * ((size + 2) / 3));
        // size/76*2 for 2 line break characters    
        if (addLineBreaks) requiredSize += requiredSize + (requiredSize / 38); 

        buffer = new byte[requiredSize];

        UInt32 octet_a;
        UInt32 octet_b;
        UInt32 octet_c;
        UInt32 triple;
        int lineCount = 0;
        int sizeMod = size - (size % 3);
        // adding all data triplets
        for (; offset < sizeMod; ) 
        {
            octet_a = data[offset++];
            octet_b = data[offset++];
            octet_c = data[offset++];

            triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;

            buffer[mBufferPos++] = base64EncodingTable[(triple >> 3 * 6) & 0x3F];
            buffer[mBufferPos++] = base64EncodingTable[(triple >> 2 * 6) & 0x3F];
            buffer[mBufferPos++] = base64EncodingTable[(triple >> 1 * 6) & 0x3F];
            buffer[mBufferPos++] = base64EncodingTable[(triple >> 0 * 6) & 0x3F];
            if (addLineBreaks)
            {
                if (++lineCount == 19)
                {
                    buffer[mBufferPos++] = 13;
                    buffer[mBufferPos++] = 10;
                    lineCount = 0;
                }
            }
        }

        // last bytes
        if (sizeMod < size)
        {
            octet_a = offset < size ? data[offset++] : (UInt32)0;
            octet_b = offset < size ? data[offset++] : (UInt32)0;
            octet_c = (UInt32)0; // last character is definitely padded

            triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;

            buffer[mBufferPos++] = base64EncodingTable[(triple >> 3 * 6) & 0x3F];
            buffer[mBufferPos++] = base64EncodingTable[(triple >> 2 * 6) & 0x3F];
            buffer[mBufferPos++] = base64EncodingTable[(triple >> 1 * 6) & 0x3F];
            buffer[mBufferPos++] = base64EncodingTable[(triple >> 0 * 6) & 0x3F];

            // add padding '='
            sizeMod = size % 3; 
            // last character is definitely padded
            buffer[mBufferPos - 1] = (byte)'=';
            if (sizeMod == 1) buffer[mBufferPos - 2] = (byte)'=';
        }
        return buffer;
    }