Click here to Skip to main content
15,890,579 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.2K   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 
byte[] bytes = new byte[] { 0x5F, 0xC9, 0xBF, 0x17 };
Console.WriteLine(Convert.ToBase64String(bytes));

which returns "X8m/Fw=="

but this is a way to turn a byte array into text using a limited subset of characters... this is not sending an integer in as few characters and as fast as possible...

if you used unsafe code to enode an eight byte integer this way it would be larger than just sending as base 10!

modified on Friday, July 4, 2008 8:17 AM

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.