摘要: base64 encode (decode) to byte array, 將 byte陣列(byte array) 以 Base64 編碼/解碼 並以 byte陣列(byte array) 作為輸出
Title: base64 encode (decode) to byte array
使用說明:
下文程式碼為使用範例,將myData 作 Base64 編碼後,再還原成未編碼的資料。
static void Main(string[] args)
{
byte[] myData = new byte[] { 125, 125};
byte[] base64 = ByteConvert.Base64Encode(myData);
byte[] rawMyData = ByteConvert.Base64Decode(base64);
}
ByteConvert 類別的原始碼:
下面的程式碼為實作 Base64 編碼/解碼 出 byte 陣列
using System;
using System.Text;
namespace Base64Byte
{
public class ByteConvert
{
private static readonly byte[] _encodeTable =
Encoding.ASCII.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/");
/// <summary>
/// Base64 encode
/// </summary>
/// <param name="data">raw data</param>
/// <returns>base64 encode data</returns>
public static byte[] Base64Encode(byte[] data)
{
if (data == null) throw new ArgumentNullException();
var bufferLen = Base64EncodeLen(data.Length);
byte[] buffer = new byte[bufferLen];
var bufferPos = 0;
UInt32 octet_a;
UInt32 octet_b;
UInt32 octet_c;
int dataPos = 0;
for (int dataLenMax = data.Length - (data.Length % 3); dataPos < dataLenMax;)
{
octet_a = data[dataPos++];
octet_b = data[dataPos++];
octet_c = data[dataPos++];
var triple = (octet_a << 0x10) | (octet_b << 0x08) | octet_c;
buffer[bufferPos++] = _encodeTable[(triple >> 3 * 6) & 0x3F];
buffer[bufferPos++] = _encodeTable[(triple >> 2 * 6) & 0x3F];
buffer[bufferPos++] = _encodeTable[(triple >> 1 * 6) & 0x3F];
buffer[bufferPos++] = _encodeTable[(triple >> 0 * 6) & 0x3F];
}
// last bytes
if (dataPos < data.Length)
{
octet_a = data[dataPos++];
octet_b = dataPos < data.Length ? data[dataPos++] : 0U;
octet_c = 0U; // last character is definitely padded
var triple = (octet_a << 0x10) | (octet_b << 0x08) | octet_c;
buffer[bufferPos++] = _encodeTable[(triple >> 3 * 6) & 0x3F];
buffer[bufferPos++] = _encodeTable[(triple >> 2 * 6) & 0x3F];
buffer[bufferPos++] = _encodeTable[(triple >> 1 * 6) & 0x3F];
buffer[bufferPos++] = _encodeTable[(triple >> 0 * 6) & 0x3F];
// add padding '='
var dataLenMod = data.Length % 3;
// last character is definitely padded
buffer[bufferPos - 1] = (byte)'=';
if (dataLenMod == 1) buffer[bufferPos - 2] = (byte)'=';
}
return buffer;
}
/// <summary>
/// Get base64 encode length
/// </summary>
/// <param name="dataLen">raw data length</param>
/// <returns>base64 encode data length</returns>
private static int Base64EncodeLen(int dataLen)
{
return ((dataLen + 2) / 3) * 4;
}
private static readonly byte[] _decodeTable = new byte[256]
{
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
64, 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, 64, 64, 64, 64, 64,
64, 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, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};
/// <summary>
/// Get base64 decode
/// </summary>
/// <param name="encodeData">base64 encode data</param>
/// <returns>base64 decode data</returns>
public static byte[] Base64Decode(byte[] encodeData)
{
if (encodeData == null) throw new ArgumentNullException();
if (encodeData.Length % 4 != 0) throw new InvalidOperationException();
int encodeDataUseLen;
var bufferLen = Base64DecodeLen(encodeData, out encodeDataUseLen);
byte[] buffer = new byte[bufferLen];
var bufferPos = 0;
UInt32 octet_a;
UInt32 octet_b;
UInt32 octet_c;
UInt32 octet_d;
int dataPos = 0;
for (int dataLenMax = encodeDataUseLen - (encodeDataUseLen % 4); dataPos < dataLenMax;)
{
octet_a = _decodeTable[encodeData[dataPos++]];
octet_b = _decodeTable[encodeData[dataPos++]];
octet_c = _decodeTable[encodeData[dataPos++]];
octet_d = _decodeTable[encodeData[dataPos++]];
var triple = (octet_a << 0x12) | (octet_b << 0x0C) | (octet_c << 0x06) | octet_d;
buffer[bufferPos++] = (byte)((triple >> 2 * 8) & 0xFF);
buffer[bufferPos++] = (byte)((triple >> 1 * 8) & 0xFF);
buffer[bufferPos++] = (byte)(triple & 0xFF);
}
var dataSurplus = encodeDataUseLen - dataPos;
if (dataSurplus == 1) throw new Exception();
// last 2~3 bytes
if (dataSurplus > 0)
{
octet_a = _decodeTable[encodeData[dataPos++]];
octet_b = _decodeTable[encodeData[dataPos++]];
octet_c = dataPos < encodeDataUseLen ? _decodeTable[encodeData[dataPos++]] : 0U;
octet_d = 0U;
var triple = (octet_a << 0x12) | (octet_b << 0x0C) | (octet_c << 0x06) | octet_d;
buffer[bufferPos++] = (byte)((triple >> 2 * 8) & 0xFF);
if (dataSurplus == 3) buffer[bufferPos++] = (byte)((triple >> 1 * 8) & 0xFF);
}
return buffer;
}
/// <summary>
/// Get base64 decode length
/// </summary>
/// <param name="encodeData">base64 encode data</param>
/// <param name="encodeDataUseLen">out: base64 encode max use length</param>
/// <returns>base64 decode data length</returns>
private static int Base64DecodeLen(byte[] encodeData, out int encodeDataUseLen)
{
int useLen = encodeData.Length;
for (int i = encodeData.Length - 1; i >= 0; --i)
{
if (encodeData[i] == '=')
{
useLen = i;
}
}
encodeDataUseLen = useLen;
return (((useLen + 3) / 4) * 3) - (encodeData.Length - useLen);
}
}
}
主要參考:
How do I base64 encode (decode) in C?
http://www.opensource.apple.com/source/QuickTimeStreamingServer/QuickTimeStreamingServer-452/CommonUtilitiesLib/base64.c
Base64 - 維基百科,自由的百科全書
※在此感謝所有的幫助者,感謝~