82

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

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?

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

5
  • what encoding is your byte array? ascii, utf8, etc? Commented Aug 29, 2012 at 12:57
  • You write that you want to convert TO base64 not "FromBase64"
    – BlueM
    Commented Aug 29, 2012 at 12:59
  • 3
    Maybe I'm missing something.. but can't you use string Convert.ToBase64String(byte[]) and byte[] Convert.FromBase64String(string)? Commented Aug 29, 2012 at 13:00
  • @SimonWhitehead I've updated my question to clarify why this is not good enough
    – sternr
    Commented Aug 29, 2012 at 13:02
  • Converting a string into bytes is another story. Use byte[] Encoding.ASCII.GetBytes(theBase64String)
    – BlueM
    Commented Aug 29, 2012 at 13:05

8 Answers 8

261

Byte[] -> String: use system.convert.tobase64string

Convert.ToBase64String(byte[] data)

String -> Byte[]: use system.convert.frombase64string

Convert.FromBase64String(string data)
9
  • 5
    can you explain a usecase where you need a base64 byte[] as byte[] ? i never in my live had this need. Commented Aug 29, 2012 at 13:04
  • 1
    Converting a string into bytes is another story. Use Encoding.ASCII.GetBytes(theString)
    – BlueM
    Commented Aug 29, 2012 at 13:04
  • 2
    @robnick: that's a huge no-go. every binary data that is getting base64'd is approx. 33% larger in size. so that's not really a useful usecase. nevertheless your usecase is just covered with byte[] -> string. Commented Dec 13, 2018 at 13:10
  • 1
    @StephanSchinkel Just try to implement downloading pdf or similar formatted files via ajax requests and you will have this problem. :) E.g. you don't have the option to open a new tab or window the current window has to be uninterrupted and in focus all the way. I don't think that 33% of any similarly formatted file counts as a very bad trade-off with the bandwidths of our time. I'm not saying its the proper way. But sometimes the business requirements demand it, thus its valid. Commented Aug 16, 2019 at 20:07
  • 1
    If you need to download a pdf or "formatted file" with ajax then just download it as a binary responsetype. No reason to convert it to text. Commented Feb 19, 2020 at 22:11
24

Base64 is a way to represent bytes in a textual form (as a string). So there is no such thing as a Base64 encoded byte[]. You'd have a base64 encoded string, which you could decode back to a byte[].

However, if you want to end up with a byte array, you could take the base64 encoded string and convert it to a byte array, like:

string base64String = Convert.ToBase64String(bytes);
byte[] stringBytes = Encoding.ASCII.GetBytes(base64String);

This, however, makes no sense because the best way to represent a byte[] as a byte[], is the byte[] itself :)

6
  • 2
    What if you would need to send the Base64 encoded form over the network? or to a file? then you will need it translated to byte[]. don't be too quick to say something makes no sense.
    – Amit Bens
    Commented Jul 28, 2013 at 12:28
  • 1
    @AmitBens sure, but if the API takes a byte[] then you can typically send the original bytes. Maybe you're thinking of a case where you embed the byte[] within a textual structure (e.g. JSON) and then send the larger structure over a binary protocol (e.g. TCP)? You'd hardly ever have to directly convert a byte array to base64 only to convert it back to a byte[] again. Commented Jul 28, 2013 at 15:25
  • 1
    @erenEsonmez - MIME for email sending, uses base64 for attachments or messages not in ascii encoding, etc. you can hardly send an email without sending a base64 representation over the wire.
    – Amit Bens
    Commented Jul 29, 2013 at 11:56
  • 1
    @ErenErsönmez Also note that some APIs require data be provided as a Base64 string (e.g. shopify). I agree its a silly but that's why people might need this. Commented Apr 4, 2018 at 13:16
  • 1
    @GeorgiG unlike your use case, OP wasn't interested in roundtrip of original bytes. See the discussions around FromBase64String in the question comments. Commented Apr 4, 2022 at 18:57
6

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 public void testBase64EncodeToBuffer()
    {
        for (int i = 1; i < 200; ++i)
        {
            // prep test data
            byte[] testData = new byte[i];
            for (int j = 0; j < i; ++j)
                testData[j] = (byte)(j ^ i);

            // test
            testBase64(testData);
        }
    }

    static void testBase64(byte[] data)
    {
        if (!appendBase64(data, 0, data.Length, false).SequenceEqual(System.Text.Encoding.ASCII.GetBytes(Convert.ToBase64String(data)))) throw new Exception("Base 64 encoding failed");
    }

    static public byte[] appendBase64(byte[] data
                              , int offset
                              , int size
                              , bool addLineBreaks = false)
    {
        byte[] buffer;
        int bufferPos = 0;
        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[bufferPos++] = base64EncodingTable[(triple >> 3 * 6) & 0x3F];
            buffer[bufferPos++] = base64EncodingTable[(triple >> 2 * 6) & 0x3F];
            buffer[bufferPos++] = base64EncodingTable[(triple >> 1 * 6) & 0x3F];
            buffer[bufferPos++] = base64EncodingTable[(triple >> 0 * 6) & 0x3F];
            if (addLineBreaks)
            {
                if (++lineCount == 19)
                {
                    buffer[bufferPos++] = 13;
                    buffer[bufferPos++] = 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[bufferPos++] = base64EncodingTable[(triple >> 3 * 6) & 0x3F];
            buffer[bufferPos++] = base64EncodingTable[(triple >> 2 * 6) & 0x3F];
            buffer[bufferPos++] = base64EncodingTable[(triple >> 1 * 6) & 0x3F];
            buffer[bufferPos++] = base64EncodingTable[(triple >> 0 * 6) & 0x3F];

            // add padding '='
            sizeMod = size % 3;
            // last character is definitely padded
            buffer[bufferPos - 1] = (byte)'=';
            if (sizeMod == 1) buffer[bufferPos - 2] = (byte)'=';
        }
        return buffer;
    }
3
  • 7
    kudos for doing it the hard way. But i will stick to System.Convert.
    – Florian F
    Commented Jul 3, 2016 at 4:02
  • @FlorianFida Sure! the downside with System.Convert is when you need to get the Base64 into a bigger buffer you end up allocating extra buffers (and easily pollute the LOH/GC if you sizes are>80k), but as long as the code is not used very frequently its definitely safe to keep to your system methods :)
    – Amit Bens
    Commented Jul 4, 2016 at 6:20
  • 2
    Amit Bens code has a good performance but till the moment you need to convert result to string or char[] (means UTF16). And this is quite often case. Then you will find it slower TWO times then System.Convert.ToBase64String. Just because of one System.Text.Encoding.ASCII.GetString(bytes) at the end. This was very unexpected for me. Commented May 10, 2017 at 22:40
5
byte[] base64EncodedStringBytes = Encoding.ASCII.GetBytes(Convert.ToBase64String(binaryData))
3

Based on your edit and comments.. would this be what you're after?

byte[] newByteArray = UTF8Encoding.UTF8.GetBytes(Convert.ToBase64String(currentByteArray));
1
  • 6
    We know that the base-64 string is going to be in the ASCII range, so it may be more efficient just to use the ASCII encoding directly (since it will be identical to what UTF8 would produce anyway) Commented Aug 29, 2012 at 13:10
0

You could use the String Convert.ToBase64String(byte[]) to encode the byte array into a base64 string, then Byte[] Convert.FromBase64String(string) to convert the resulting string back into a byte array.

0

To retrieve your image from byte to base64 string....

Model property:

    public byte[] NomineePhoto { get; set; }

    public string NomineePhoneInBase64Str 
    {
        get {
            if (NomineePhoto == null)
                return "";

            return $"data:image/png;base64,{Convert.ToBase64String(NomineePhoto)}";
        } 
    }

IN view:

   <img style="height:50px;width:50px" src="@item.NomineePhoneInBase64Str" />
-1
    public void ProcessRequest(HttpContext context)
    {
        string constring = ConfigurationManager.ConnectionStrings["SQL_Connection_String"].ConnectionString;
        SqlConnection conn = new SqlConnection(constring);
        conn.Open();
        SqlCommand cmd = new SqlCommand("select image1 from TestGo where TestId=1", conn);
        SqlDataReader dr = cmd.ExecuteReader();
        dr.Read();
        MemoryStream str = new MemoryStream();

        context.Response.Clear();
        Byte[] bytes = (Byte[])dr[0];
        string d = System.Text.Encoding.Default.GetString(bytes);
        byte[] bytes2 = Convert.FromBase64String(d);
        //context.Response.Write(d);
        Image img = Image.FromStream(new MemoryStream(bytes2));
        img.Save(context.Response.OutputStream, ImageFormat.Png);
        context.Response.Flush();
        str.WriteTo(context.Response.OutputStream);
        str.Dispose();
        str.Close();
        conn.Close();
        context.Response.End();
    }
1
  • 2
    I can see your answer getting down votes. Please explain your answer to avoid downvotes from the community in the future.
    – user10314103
    Commented Jan 12, 2019 at 13:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.