title: Convert a bytes array to base64

text:
# Question
Title: Convert a bytes array to base64
Your mission is to write a function/program that converts an array of bytes (i.e: an array of integers from 0 to 255), to base64.

Using built-in base64 encoders is not allowed.

The required base64 implementation is RFC 2045. (using "+", "/", and mandatory padding with "=")

Shortest code (in bytes) wins!

## Example:

Input (int array): `[99, 97, 102, 195, 169]`

Output (string): `Y2Fmw6k=`

# Answer
> 5 votes
# JavaScript, 177 ~~187~~ ~~198~~ characters

```
function(d){c="";for(a=e=b=0;a<4*d.length/3;f=b>>2*(++a&3)&63,c+=String.fromCharCode(f+71-(f<26?6:f<52?0:f<62?75:f^63?90:87)))a&3^3&&(b=b<<8^d[e++]);for(;a++&3;)c+="=";return c}

```

For adding linebreaks, `\r\n`, after each 76th character, add 23 characters to the code:

```
function(d){c="";for(a=e=b=0;a<4*d.length/3;f=b>>2*(++a&3)&63,c+=String.fromCharCode(f+71-(f<26?6:f<52?0:f<62?75:f^63?90:87))+(75==(a-1)%76?"\r\n":""))a&3^3&&(b=b<<8^d[e++]);for(;a++&3;)c+="=";return c}

```

Demo code:

```
var encode = function(d,a,e,b,c,f){c="";for(a=e=b=0;a<4*d.length/3;f=b>>2*(++a&3)&63,c+=String.fromCharCode(f+71-(f<26?6:f<52?0:f<62?75:f^63?90:87))+(75==(a-1)%76?"\r\n":""))a&3^3&&(b=b<<8^d[e++]);for(;a++&3;)c+="=";return c};

//OP test case
console.log(encode([99, 97, 102, 195, 169])); // outputs "Y2Fmw6k=".

//Quote from Hobbes' Leviathan:
console.log(
 encode(
  ("Man is distinguished, not only by his reason, but by this singular passion from " +
   "other animals, which is a lust of the mind, that by a perseverance of delight " +
   "in the continued and indefatigable generation of knowledge, exceeds the short " +
   "vehemence of any carnal pleasure.")
  .split('').map(function(i){return i.charCodeAt(0)})
 )
);
```

# Answer
> 4 votes
# C, 276 bytes

Quite a bump of this thread but I came up with this question myself a few days ago, then found out about code golfing, then found out about this thread.

Takes the 0-255 int array as first console arg (just a string). Uses K&R C style function parameter declaration and RFC 2045 encoding (except with no 76-character limit).

```
#define u(_)unsigned _:6;
b(i,j){putchar(j?i>61?43+i%2*4:i+65+6*(i>25)-75*(i>51):61);}i=-3;main(o,c)char**c;{char*s=c[1];for(;(i+=3)<strlen(s);){union{struct{u(a)u(b)u(c)u(d)};char s[3];}a;a.s[2]=s[i];a.s[1]=s[i+1];*a.s=s[i+2];b(a.d);b(a.c);b(a.b,a.s[1]);b(a.a,a.s[1]**a.s);}}

```

More 'readable' version of the algorithm (it was originally more clear but I started obfusc-golfing it right away so it turned out like this):

```
#include <stdio.h>
#include <string.h>

void b64_char(int i) {
    putchar(i>61?43+i%2*4:i+65+6*(i>25)-75*(i>51));
}

int i=-3;
int main(int argc, char* argv[]) {
    char* str = argv[1];
    for (;(i+=3)<strlen(str);) {
        union {
            struct {unsigned a:6; unsigned b:6; unsigned c:6; unsigned d:6;};
            char s[3];
        } a;
        a.s[2]=str[i];
        a.s[1]=str[i+1];
        a.s[0]=str[i+2];

        b64_char(a.d);
        b64_char(a.c);
        a.s[1]?b64_char(a.b):putchar(61);
        a.s[0]&&a.s[1]?b64_char(a.a):putchar(61);
    }

    return 0;
}

```

Defining the Base64 symbol table like that saved me a bunch of bytes. Basically taking advantage of the consecutiveness of letters in ASCII.

Also, architecture dependent since it only works on little endian machines, and fails non-deterministically when the unpassed parameter for the function `b(2)` happens to be 0. This would have been a lot shorter on a big endian machine.

Can anybody shorten this any further?

# Answer
> 3 votes
## 32-bit x86 assembly, 59 bytes

Byte-code:

```
66 B8 0D 0A 66 AB 6A 14 5A 4A 74 F4 AD 4E 45 0F C8 6A 04 59 C1 C0 06 24 3F 3C 3E 72 05 C0
E0 02 2C 0E 2C 04 3C 30 7D 08 04 45 3C 5A 76 02 04 06 AA 4D E0 E0 75 D3 B0 3D F3 AA C3
```

Disassembly:

```
b64_newline:
    mov     ax, 0a0dh
    stosw
b64encode:
    push    (76 shr 2) + 1
    pop     edx
b64_outer:
    dec     edx
    je      b64_newline
    lodsd
    dec     esi
    inc     ebp
    bswap   eax
    push    4
    pop     ecx
b64_inner:
    rol     eax, 6
    and     al, 3fh
    cmp     al, 3eh
    jb      b64_testchar
    shl     al, 2     ;'+' and '/' differ by only 1 bit
    sub     al, ((3eh shl 2) + 'A' - '+') and 0ffh
b64_testchar:
    sub     al, 4
    cmp     al, '0'
    jnl     b64_store ;l not b because '/' is still < 0 here
    add     al, 'A' + 4
    cmp     al, 'Z'
    jbe     b64_store
    add     al, 'a' - 'Z' - 1
b64_store:
    stosb
    dec     ebp
    loopne  b64_inner
    jne     b64_outer
    mov     al, '='
    rep     stosb
    ret
```

Call b64encode with esi pointing to input buffer, edi pointing to output buffer.

It could be made even smaller if line-wrapping is not used.

# Answer
> 3 votes
# Husk, ~~118~~ ~~114~~ ~~93~~ ~~82~~ ~~73~~ 61 bytes

```
C76ΣtTT'=C4§o↓_ȯa%_3L(mo!ṁ…w"AZ az 09 + /"→B64B256ΣTT0C3+R3 4

```

Try it online!

## Examples

* \[\]:LN "" (LN is a type hint for list of numbers)
* \[0\] "AA=="
* \[99,97,102,195,169\] "Y2Fmw6k="
* \[108,105,103,104,116,32,119,111,114,107,46\] "bGlnaHQgd29yay4="

## How it works

```
C76ΣtTT'=C4§o↓_ȯa%_3L(mo!ṁ…w"AZ az 09 + /"→B64B256ΣTT0C3+R3 4
           §    Main fork combinator.
                                                        +R3 4    Begin first branch of the fork. Prepend 3 4s to deal with leading zeros.
                                                  ΣTT0C3    Chop into 3-byte chunks. Transpose with 0 padding, transpose back, and flatten.
                                           B64B256    Interpret as base 256, then as base 64.
                     (mo!ṁ…w"AZ az 09 + /"→    Map the following: increment (Husk is 1-based) and index into the base 64 alphabet. End first branch of fork.
               ȯa%_3L    Second branch of the fork: padding = abs(length mod -3)
            o↓_    Converge the fork on this function: Drop padding number of characters from the end of the base 64 encoded string.
   ΣtTT'=C4    Chop into 4-character chunks, transpose with '=' padding, transpose back, drop the first chunk, and flatten.
C76    Chop the encoded string into 76-character chunks which will be joined with '\r\n' automatically.

```

This is my first code-golf submission and I would appreciate any help from the Husk experts here!

Thank you Leo for your help with the 61-byte version!!

# Answer
> 2 votes
# Excel 2016+, <sub>~~209~~</sub> 205 Bytes

An anonymous function that take input as a dynamic, spilled or legacy array from range `A1#` and outputs to the calling cell.

```
=LET(c,COUNT(A1#),i,CONCAT(MID(CONCAT(CHAR({64;96}+COLUMN(A:Z)),"0123456789+/"),1+BIN2DEC(MID(CONCAT(BASE(A1#,2,8))&REPT("00",MOD(c,3)),SEQUENCE(4*c/3+.7,,,6),6)),1)),j,MOD(LEN(i),4),i&REPT("=",IF(j,4-j)))

```

## Ungolfed

```
=LET(                                           ' Begin Variable block
    c,COUNT(A1#),                               '   Def c(ount) with count of bytes in array
    i,CONCAT(                                   '   Def i helper var holding the string concatenated from
        MID(                                    '     Repeatedly splitting
            CONCAT(                             '       The Base64 alphabet, made by concating
                CHAR({64;96}+COLUMN(A:Z)),      '          uppercase and lowercase alphas
                "0123456789+/"),                '          numbers and symbols
            1+BIN2DEC(                          '       at index of 1+ decimal value from binary string obtained from
                MID(                            '         splitting
                    CONCAT(                     '           the string concatenated from
                        BASE(A1#,2,8),          '             the binary string array representation of input
                        REPT("00",MOD(c,3))),   '             padded with `0` to lowest even multiple of 6 bits larger than c
                    SEQUENCE(4*c/3+.7,,,6),     '           at every sixth char, for a total of ceil(4/3*count(input)) string
                    6)),                        '           making each substring be a binary string of 6 bits
            1)),                                '       with length 1
    j,MOD(LEN(i),4),                            '   Def j as the helper var holding length of i mod 4
    i&REPT("=",IF(j,4-j)))                      ' Output i and `=` padding to a string length that is a multiple 4

```

# Answer
> 1 votes
# perl, 126 bytes

reads stdin, outputs to stdout

```
$/=$\;print map{$l=y///c/2%3;[A..Z,a..z,0..9,"+","/"]->[oct"0b".substr$_.0 x4,0,6],$l?"="x(3-$l):""}unpack("B*",<>)=~/.{1,6}/g

```

ungolfed:

```
my @x = ('A'..'Z','a'..'z',0..9,'+','/');
my $in = join '', <>;
my $bits = unpack 'B*', $in;
my @six_bit_groups = $bits =~ /.{1,6}/g;
for my $sixbits (@six_bit_groups) {
  next unless defined $sixbits;
  $l=length($sixbits)/2%3;
  my $zero_padded = $sixbits . ( "0" x 4 );
  my $padded_bits = substr( $zero_padded, 0, 6 );
  my $six_bit_int = oct "0b" . $padded_bits;
  print $x[$six_bit_int];
  print "=" x (3 - $l)  if  $l;
}

```

# Answer
> 1 votes
## Python, 234 chars

```
def F(s):
 R=range;A=R(65,91)+R(97,123)+R(48,58)+[43,47];n=len(s);s+=[0,0];r='';i=0
 while i<n:
  if i%57<1:r+='\r\n'
  for j in R(4):r+=chr(A[s[i]*65536+s[i+1]*256+s[i+2]>>18-6*j&63])
  i+=3
 k=-n%3
 if k:r=r[:-k]+'='*k
 return r[2:]

```

# Answer
> 1 votes
# Perl, 147 bytes

```
sub b{$f=(3-($#_+1)%3)%3;$_=unpack'B*',pack'C*',@_;@r=map{(A..Z,a..z,0..9,'+','/')[oct"0b$_"]}/.{1,6}/g;$"='';join"\r\n",("@r".'='x$f)=~/.{1,76}/g}

```

The function takes a list of integers as input and outputs the string, base64 encoded.

**Example:**

```
print b(99, 97, 102, 195, 169)

```

prints

```
Y2Fmw6kA

```

**Ungolfed:**

Version that also visualizes the intermediate steps:

```
sub b {
    # input array: @_
    # number of elements: $#_ + 1 ($#_ is zero-based index of last element in
    $fillbytes = (3 - ($#_ + 1) % 3) % 3;
      # calculate the number for the needed fill bytes
      print "fillbytes:       $fillbytes\n";
    $byte_string = pack 'C*', @_;
      # the numbers are packed as octets to a binary string
      # (binary string not printed)
    $bit_string = unpack 'B*', $byte_string;
      # the binary string is converted to its bit representation, a string wit
      print "bit string:      \"$bit_string\"\n";
    @six_bit_strings = $bit_string =~ /.{1,6}/g;
      # group in blocks of 6 bit
      print "6-bit strings:   [@six_bit_strings]\n";
    @index_positions = map { oct"0b$_" } @six_bit_strings;
      # convert bit string to number
      print "index positions: [@index_positions]\n";
    @alphabet = (A..Z,a..z,0..9,'+','/');
      # the alphabet for base64
    @output_chars = map { $alphabet[$_] } @index_positions;
      # output characters with wrong last characters that entirely derived fro
      print "output chars:    [@output_chars]\n";
    local $" = ''; #"
    $output_string = "@output_chars";
      # array to string without space between elements ($")
      print "output string:   \"$output_string\"\n";
    $result = $output_string .= '=' x $fillbytes;
      # add padding with trailing '=' characters
      print "result:          \"$result\"\n";
    $formatted_result = join "\r\n", $result =~ /.{1,76}/g;
      # maximum line length is 76 and line ends are "\r\n" according to RFC 2045
      print "formatted result:\n$formatted_result\n";
    return $formatted_result;
}

```

**Output:**

```
fillbytes:       1
bit string:      "0110001101100001011001101100001110101001"
6-bit strings:   [011000 110110 000101 100110 110000 111010 1001]
index positions: [24 54 5 38 48 58 9]
output chars:    [Y 2 F m w 6 J]
output string:   "Y2Fmw6J"
result:          "Y2Fmw6J="
formatted result:
Y2Fmw6J=

```

**Tests:**

The test strings come from the example in the question the examples in the Wikipedia article for Base64.

```
sub b{$f=(3-($#_+1)%3)%3;$_=unpack'B*',pack'C*',@_;@r=map{(A..Z,a..z,0..9,'+','/')[oct"0b$_"]}/.{1,6}/g;$"='';join"\r\n",("@r".'='x$f)=~/.{1,76}/g}

sub test ($) {
   print b(map {ord($_)} $_[0] =~ /./sg), "\n\n";
}

my $str = <<'END_STR';
Man is distinguished, not only by his reason, but by this singular passion from
other animals, which is a lust of the mind, that by a perseverance of delight
in the continued and indefatigable generation of knowledge, exceeds the short
vehemence of any carnal pleasure.
END_STR
chomp $str;

test "\143\141\146\303\251";
test $str;
test "any carnal pleasure.";
test "any carnal pleasure";
test "any carnal pleasur";
test "any carnal pleasu";
test "any carnal pleas";
test "pleasure.";
test "leasure.";
test "easure.";
test "asure.";
test "sure.";

```

Test output:

```
TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
IHNpbmd1bGFyIHBhc3Npb24gZnJvbQpvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodAppbiB0aGUgY29udGlu
dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
ZSBzaG9ydAp2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZSO=

YW55IGNhcm5hbCBwbGVhc3VyZSO=

YW55IGNhcm5hbCBwbGVhc3VyZB==

YW55IGNhcm5hbCBwbGVhc3Vy

YW55IGNhcm5hbCBwbGVhc3F=

YW55IGNhcm5hbCBwbGVhcD==

cGxlYXN1cmUu

bGVhc3VyZSO=

ZWFzdXJlLC==

YXN1cmUu

c3VyZSO=

```

# Answer
> 1 votes
# GolfScript, 80 (77) bytes

```
~.,~)3%:P[0]*+[4]3*\+256base 64base{'+/''A[a{:0'{,^}/=}/{;}P*'='P*]4>76/"\r
":n*

```

The above will fit exactly 76 characters in a line, except for the last line. All lines are terminated by CRLF.

Note that RFC 2045 specifies a *variable, maximum* line length of 76 characters, so at the cost of pretty output, we can save 3 additional bytes.

```
~.,~)3%:P[0]*+[4]3*\+256base 64base{'+/''A[a{:0'{,^}/=}/{;}P*'='P*]4>{13]n+}/

```

The above will print one character per line, except for the last line, which can contain 0, 1 or 2 `=` chars. GolfScript will also append a final LF, which, according to RFC 2045, must be ignored by decoding software.

### Example

```
$ echo '[99 97 102 195 169]' | golfscript base64.gs | cat -A
Y2Fmw6k=^M$
$ echo [ {0..142} ] | golfscript base64.gs | cat -A
AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4^M$
OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx^M$
cnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY4=^M$
$ echo '[99 97 102 195 169]' | golfscript base64-sneaky.gs | cat -A
Y^M$
2^M$
F^M$
m^M$
w^M$
6^M$
k^M$
=^M$
$

```

### How it works

```
~          # Interpret the input string.
.,~)3%:P   # Calculate the number of bytes missing to yield a multiple of 3 and save in “P”.
[0]*+      # Append that many zero bytes to the input array.
[4]3*\+    # Prepend 3 bytes to the input array to avoid issues with leading zeros.
256base    # Convert the input array into an integer.
64base     # Convert that integer to base 64.
{          # For each digit:
  '+/'     # Push '+/'.
  'A[a{:0' # Push 'A[a{:0'.
  {        # For each byte in 'A[a{:0':
    ,      # Push the array of all bytes up to that byte.
    ^      # Take the symmetric difference with the array below it.
  }/       # Result: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  =        # Retrieve the character corresponding to the digit.
}/         #
{;}P*'='P* # Replace the last “P” characters with a string containing that many “=” chars.
]          # Collect all bytes on the stack into an array.
4>         # Remove the first four, which correspond to the 3 prepended bytes.
76/        # Collect all bytes on the stack into an array and split into 76-byte chunks.
"\r\n":n*  # Join the chunks with separator CRLF and save CRLF as the new line terminator.

```

# Answer
> 1 votes
# PHP, 200 bytes

```
<?foreach($g=$_GET as$k=>$v)$b[$k/3^0]+=256**(2-$k%3)*$v;for(;$i<62;)$s.=chr($i%26+[65,97,48][$i++/26]);foreach($b as$k=>$v)for($i=4;$i--;$p++)$r.=("$s+/=")[count($g)*4/3<$p?64:($v/64**$i)%64];echo$r;

```

Try it online!

You could replace the string `("$s+/=")` with an array `array_merge(range(A,Z),range(a,z),range(0,9),["+","/","="])`

Only to compare which byte count can reach with an not allowed built-in

PHP, 45 bytes

```
<?=base64_encode(join(array_map(chr,$_GET)));

```

Try it online!

# Answer
> 0 votes
# Python - ~~310~~, 333

```
def e(b):
  l=len;c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";r=p="";d=l(b)%3
  if d>0:d=abs(d-3);p+="="*d;b+=[0]*d
  for i in range(0,l(b)-1,3):
    if l(r)%76==0:r+="\r\n"
    n=(b[i]<<16)+(b[i+1]<<8)+b[i+2];x=(n>>18)&63,(n>>12)&63,(n>>6)&63,n&63;r+=c[x[0]]+c[x[1]]+c[x[2]]+c[x[3]]
  return r[:l(r)-l(p)]+p

```

Somewhat ungolfed:

```
def e( b ):
    c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    r = p = ""
    d = len( b ) % 3

    if d > 0:
        d = abs( d - 3 )
        p = "=" * d
        b + = [0] * d

    for i in range( 0, len( b ) - 1, 3 ):
        if len( r ) % 76 == 0:
            r += "\r\n"

        n = ( b[i] << 16 ) + ( b[i + 1] << 8 ) + b[i + 2]
        x = ( n >> 18 ) & 63, ( n >> 12 ) & 63, ( n >> 6) & 63, n & 63
        r += c[x[0]] + c[x[1]] + c[x[2]] + c[x[3]]

    return r[:len( r ) - len( p )] + p

```

**Example**:

Python's built-in base64 module is only used in this example to ensure the `e` function has the correct output, the `e` function itself isn't using it.

```
from base64 import encodestring as enc

test = [ 99, 97, 102, 195, 169 ]
str  = "".join( chr( x ) for x in test )

control = enc( str ).strip()
output = e( test )

print output            # => Y2Fmw6k=
print control == output # => True

```

# Answer
> 0 votes
## JavaScript (ES6), 220B

```
f=a=>{for(s=a.map(e=>('0000000'+e.toString(2)).slice(-8)).join(p='');s.length%6;p+='=')s+='00';return s.match(/.{6}/g).map(e=>'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'[parseInt(e,2)]).join('')+p}

```

If your browser does not support ES6, you can try with this version (262B) :

```
function f(a){for(s=a.map(function(e){return ('0000000'+e.toString(2)).slice(-8)}).join(p='');s.length%6;p+='=')s+='00';return s.match(/.{6}/g).map(function(e){return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'[parseInt(e,2)]}).join('')+p}

```

`f([99, 97, 102, 195, 169])` returns `"Y2Fmw6k="`.

# Answer
> 0 votes
# Jelly, 38 bytes

```
s3z0Zµḅ⁹b64‘ịØb)FṖ³LN%3¤¡s4z”=Z;€“Æ½‘Ọ

```

Try it online!

As (almost) every other answer covers the RFC2045 requirement of "at most 76 chars per line with line ending `\r\n`", I followed it.

### How it works

```
s3z0Zµḅ⁹b64‘ịØb)FṖ³LN%3¤¡s4z”=Z;€“Æ½‘Ọ    Monadic main link. Input: list of bytes

s3z0Z    Slice into 3-item chunks, transpose with 0 padding, transpose back
         Equivalent to "pad to length 3n, then slice into chunks"

µḅ⁹b64‘ịØb)    Convert each chunk to base64
 ḅ⁹b64         Convert base 256 to integer, then to base 64
      ‘ịØb     Increment (Jelly is 1-based) and index into base64 digits

FṖ³LN%3¤¡s4z”=Z    Add correct "=" padding
F                  Flatten the list of strings to single string
 Ṗ      ¡          Repeat "remove last" n times, where
  ³LN%3¤             n = (- input length) % 3
         s4z”=Z    Pad "=" to length 4n, then slice into 4-item chunks

;€“Æ½‘Ọ    Add "\r\n" line separator
;€         Append to each line:
  “Æ½‘       Codepage-encoded list [13,10]
      Ọ    Apply `chr` to numbers; effectively add "\r\n"

```

---
Tags: code-golf, base-conversion, encoding
---