Click here to Skip to main content
15,881,881 members
Articles / Programming Languages / C#
Article

Convert an integer to a base 64 string and back again very quickly

Rate me:
Please Sign up or sign in to vote.
2.77/5 (9 votes)
4 Jul 2008Public Domain1 min read 64.1K   305   23   10
Convert a positive 32 bit integer to a base 64 string. This is the fastest and shortest encoding / decoding of an integer to / from text. Easily modified for 64 bit integers.

Introduction

I often have to encode positive integer IDs into text to send over a socket, and like to keep the messages as short as possible and the encoding / decoding as fast as possible. Using C#, it's easy to send your integer ID as base 10 or base 16 strings, but using base 64 or base 62 or base 36 or base 32 encoded strings saves a lot of space. There is another article on this site encoding and decoding base 36 integers, but it uses Math.Pow, which is very slow.

By choosing Base 64 (made from 0-9, A-Z, a-z, +, -) which fits perfectly into 6 bits, I can encode and decode very quickly. I can also fit a nine or ten digit base 10 Int32 into a five character base 64 string.

In fact, this app shows that C#'s Convert.ToInt32 followed by Convert.ToString is 5½ times slower than using my base 64 encoding functions!

The code is very simple, and easily modified to Int64 or passing a char[] with offset, which is useful for socket stuff. For the encode, you choose the number of characters to encode into. One character gives you 0-63, of course, two is 4096, three 262,144 etc.

It would be easy to translate to C or C++ as well. If you download the app, you can see some demonstrations and a speed test using the high performance timer. But otherwise, all the code you need is here:

C#
using System;
using System.Collections.Generic;
using System.Text;

class Base64
{
    static char[] b64e = new char[] {  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
                       'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 
                       'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 
                       'U', 'V', 'W', 'X', 'Y', 'Z', 
                       'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 
                       'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 
                       'u', 'v', 'w', 'x', 'y', 'z', 
                       '+', '/'};

    static int[] b64d = new int[] {    000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,062,000,000,000,063,000,001,
                                   002,003,004,005,006,007,008,009,000,000,
                                   000,000,000,000,000,010,011,012,013,014,
                                   015,016,017,018,019,020,021,022,023,024,
                                   025,026,027,028,029,030,031,032,033,034,
                                   035,000,000,000,000,000,000,036,037,038,
                                   039,040,041,042,043,044,045,046,047,048,
                                   049,050,051,052,053,054,055,056,057,058,
                                   059,060,061,000,000,000,000,000,000,000, 
                                   000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,000,000,000,000,000,000,000, 
                                   000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,000,000,000,000,000,000,000, 
                                   000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,000,000,000,000,000,000,000,
                                   000,000,000,000,000,000,000,000,000,000, 
                                   000,000,000,000,000,000};                

    public static string b64ConvertInt(int value, int length) 
    {
        // length should be between 1 and 5 only
        if (length == 5)
        {
            char[] c = new char[5];
            c[0] = b64e[(value & 1056964608) >> 24];
            c[1] = b64e[(value & 16515072) >> 18];
            c[2] = b64e[(value & 258048) >> 12];
            c[3] = b64e[(value & 4032) >> 06];
            c[4] = b64e[(value & 63)];
            return new string(c);
        }
        else if (length == 4)
        {
            char[] c = new char[4];
            c[0] = b64e[(value & 16515072) >> 18];
            c[1] = b64e[(value & 258048) >> 12];
            c[2] = b64e[(value & 4032) >> 06];
            c[3] = b64e[(value & 63)];
            return new string(c);
        }
        else if (length == 3)
        {
            char[] c = new char[3];
            c[0] = b64e[(value & 258048) >> 12];
            c[1] = b64e[(value & 4032) >> 06];
            c[2] = b64e[(value & 63)];
            return new string(c);
        }
        else if (length == 2)
        {
            char[] c = new char[2];
            c[0] = b64e[(value & 4032) >> 06];
            c[1] = b64e[(value & 63)];
            return new string(c);
        }
        else
        {
            return Convert.ToString(b64e[(value & 63)]);
        }
    }

    public static int b64ConvertString(string s) 
    { // string s should be between 1 and 5 character long only

        int n = s.Length;
        char[] c = s.ToCharArray();
        if (n == 5)
        {
            return (b64d[c[0]] << 24) + (b64d[c[1]] << 18) + 
                   (b64d[c[2]] << 12) + (b64d[c[3]] << 6) + b64d[c[4]];
        }
        else if (n == 4)
        {
            return (b64d[c[0]] << 18) + (b64d[c[1]] << 12) + 
                   (b64d[c[2]] << 6) + b64d[c[3]];
        }
        else if (n == 3)
        {
            return (b64d[c[0]] << 12) + (b64d[c[1]] << 6) + b64d[c[2]];
        }
        else if (n == 2)
        {
            return (b64d[c[0]] << 6) + b64d[c[1]];
        }
        else if (n == 1)
        {
            return b64d[c[0]];
        }

        return 0;
    }
}

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication



Comments and Discussions

 
QuestionHow do I have a larger character set to encode? Than 64? Pin
frankii915-Mar-22 11:10
frankii915-Mar-22 11:10 
Suggestionmore readable approach for bitand operatios Pin
milczuk10-Jul-12 6:01
milczuk10-Jul-12 6:01 
GeneralAh dang, another quibble. [modified] Pin
PIEBALDconsult4-Jul-08 5:40
mvePIEBALDconsult4-Jul-08 5:40 
Generalthis is not a all purpose class to convert into different bases [modified] Pin
w.hooper6-Jul-08 19:37
w.hooper6-Jul-08 19:37 
GeneralChoice of characters Pin
PIEBALDconsult4-Jul-08 5:18
mvePIEBALDconsult4-Jul-08 5:18 
GeneralSomeone should take a switch to you Pin
PIEBALDconsult4-Jul-08 4:23
mvePIEBALDconsult4-Jul-08 4:23 
QuestionDo you realise this is already present in the .NET framework? Pin
leppie4-Jul-08 1:42
leppie4-Jul-08 1:42 
AnswerWrong .. you are getting confused with Convert.ToBase64String for general purpose byte encoding [modified] Pin
w.hooper4-Jul-08 1:56
w.hooper4-Jul-08 1:56 
GeneralRe: Wrong .. you are getting confused with Convert.ToBase64String for general purpose byte encoding Pin
leppie4-Jul-08 4:39
leppie4-Jul-08 4:39 
AnswerRe: Do you realise this is already present in the .NET framework? Pin
PIEBALDconsult4-Jul-08 4:12
mvePIEBALDconsult4-Jul-08 4:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.