How does Base64 encoding work?

Base64 encoding scheme is designed to encode binary data, especially when that data needs to be stored and transferred over media that designed to deal with text. Base64 encoding helps to ensure that the data remains intact without modification during transport.

Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation. Base64 is used commonly in a number of applications including email via MIME (Multipurpose Internet Mail Extensions), and storing complex data in XML or JSON.

Radix-64 refers to a numeral system that uses 64 unique characters to represent data. In the case of Base64 encoding, the 64 characters are typically the uppercase letters AZ, the lowercase letters az, the numerals 09, and an additional two characters, usually + and /. These characters are used to encode data into a text format that can be safely transferred over various systems designed to handle text data.

Here’s a brief overview of how the Base64 encoding process works:

  • Take the input data (which is binary data). For example, we have the text “Hello”. Each character is converted into their ASCII code.
  • Split the input data into chunks of 24 bits (3 bytes). If the input is not divisible by 24, it is padded with zeros on the right to make up a full chunk.
ASCII H = 72 e = 101 l = 108 l = 108 o = 111
Binary 01001000 01100101 01101100 01101100 01101111
  • Each chunk of 24 bits is then split into four chunks of 6 bits.
6-bits 010010 000110 010101 101100
Value 18 6 21 44
6-bits 011011 000110 111100 [00 = PAD]
Value 27 6 60
  • Each 6-bit chunk is then mapped to an encoded character using an index table (below), which is a set of 64 distinct characters—these are A–Z, a–z, 0–9, + and / in the Base64 alphabet.
Value 18 6 21 44 27 6 60
Encoding S G V s b G 8
  • If the last 8-bit block (third block for normal Base64 encoding) had the padding zero bits, the output of the corresponding 6-bit block (fourth block for normal Base64 encoding) is replaced with one = symbol. If the second 8-bit block also had padding zeros, then fourth, and third blocks of Base64 encoding will have = symbols.
Value 18 6 21 44 27 6 60 PAD
Encoding S G V s b G 8 =
  • The output is the encoded string.
SGVsbG8=

This process can be reversed to decode a Base64 string back into the original binary data.

Do note, though, while Base64 can encode any binary data, it is not encryption nor should it be used for encryption purposes – it does not hide or secure information, it’s merely an encoding scheme.

Base64 Index Table

Value Encoding Value Encoding Value Encoding Value Encoding
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /

Differences between getEncoder() and getUrlEncoder() method of java.util.Base64 class

The java.util.Base64.getEncoder() and java.util.Base64.getUrlEncoder() methods in Java both return a Base64 encoder. However, they exhibit different behaviors mainly due to the encoding scheme they follow for handling URL and filename safe characters.

  • java.util.Base64.getEncoder(): This method returns a Base64.Encoder that encodes using the Basic type base64 encoding scheme as per RFC 4648 Section 4.

Basic Base64 encoding does not handle URL and filename safe characters well. It uses + for 62, / for 63, and = for padding. These characters can cause problems in URLs.

An example of its usage.

package org.kodejava.util;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Base64EncoderExample {
    public static void main(String[] args) {
        Base64.Encoder encoder = Base64.getEncoder();
        String str = "https://www.google.com/search?q=Hello+World";
        String encodedString = encoder.encodeToString(str.getBytes(StandardCharsets.UTF_8));
        System.out.println("encodedString = " + encodedString);
    }
}

Output:

encodedString = aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9zZWFyY2g/cT1IZWxsbytXb3JsZA==
  • java.util.Base64.getUrlEncoder(): This method returns a Base64.Encoder that encodes in URL and filename safe type base64 scheme as per RFC 4648 Section 5.

URL and filename safe Base64 encoding replaces + with - , and / with _. It also omits padding characters. This makes it safer for use in URLs or file-system paths.

An example of its usage.

package org.kodejava.util;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Base64UrlEncoderExample {
    public static void main(String[] args) {
        Base64.Encoder urlEncoder = Base64.getUrlEncoder();
        String str = "https://www.google.com/search?q=Hello+World";
        String urlEncodedString = urlEncoder.encodeToString(str.getBytes(StandardCharsets.UTF_8));
        System.out.println("encodedString = " + urlEncodedString);
    }
}

Output:

encodedString = aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9zZWFyY2g_cT1IZWxsbytXb3JsZA==

So the choice between these two would depend on where you intend to use the encoded bytes. If it’s to be in a URL or a filepath, it’s recommended to use the getUrlEncoder() due to its url safe encoding scheme. For other use cases, the getEncoder() method should suffice.

Similar to the getEncoder() and getUrlEncoder() methods, the java.util.Base64 class provides the getDecoder() and getUrlDecoder() methods for Base64 decoding.

  • java.util.Base64.getDecoder(): This method returns a Base64.Decoder that decodes using the Basic type base64 encoding scheme.

Example:

package org.kodejava.util;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Base64DecodeExample {
    public static void main(String[] args) {
        Base64.Decoder decoder = Base64.getDecoder();

        // "Hello, World!" in Base64
        String str = "SGVsbG8sIFdvcmxkIQ==";
        String decodedString = new String(decoder.decode(str), StandardCharsets.UTF_8);
        System.out.println("decodedString = " + decodedString);
    }
}

Output:

decodedString = Hello, World!
  • java.util.Base64.getUrlDecoder(): This method returns a Base64.Decoder that decodes using the URL and Filename safe type base64 encoding scheme.

Example:

package org.kodejava.util;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Base64UrlDecoderExample {
    public static void main(String[] args) {
        Base64.Decoder urlDecoder = Base64.getUrlDecoder();

        // "Hello, World!" in URL-safe Base64
        String urlSafeStr = "SGVsbG8sIFdvcmxkIQ";
        String decodedString = new String(urlDecoder.decode(urlSafeStr), StandardCharsets.UTF_8);
        System.out.println("decodedString = " + decodedString);
    }
}

Output:

decodedString = Hello, World!

The choice between these two would again depend on from where you are getting the encoded bytes. If it’s from a URL or a filepath, you would want to use getUrlDecoder(). For other use cases, the getDecoder() method should suffice.

How do I convert Base64 string to image file?

In the previous example, How do I convert an image file to a Base64 string?, you’ve seen how to convert image file to base64 string.

In this example, you will see how you can convert a base64 string back into an image file. Below are examples of how to do this in Java, using the Java 8 native java.util.Base64 class.

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;

public class Base64ToImage {
    public static void main(String[] args) throws Exception {
        // this is your Base64 encoded string
        String base64String = "iVBORw0...";

        byte[] decodedBytes = Base64.getDecoder().decode(base64String);
        Files.write(Paths.get("/path/to/your/outputimage.png"), decodedBytes);
    }
}

Just replace “/path/to/your/outputimage.png” with the actual path where you want to save the image.

This code will decode the base64 string back into a byte array, and then it will write this byte array into an image file. Be careful with the format of the image (PNG, JPG, etc.) as the format of the output file should match the format of the original base64-encoded image.

How do I convert an image file to a Base64 string?

A Base64 string is a way of encoding binary data using 64 printable characters, which are the 26 uppercase letters of the English alphabet, the 26 lowercase letters of the English alphabet, the 10 numerical digits, and the “+” and “/” symbols. This makes a total of 64 distinct characters, hence the name “Base64”.

Base64 encoding is commonly used when there is a need to encode binary data, especially when that data needs to be stored and transferred over media that is designed to handle text.

The primary use case of this encoding is to allow binary data to be represented in a way that looks and acts as plain text. For example, embedded images in HTML (often as data URIs), and storing complex data in XML or JSON.

In Java, you can use the java.util.Base64 classes to convert an image file to a base64 String. You can use it to convert a JPG or a PNG image file, or basically any binary image files. Here is a simple example:

package org.kodejava.util;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;

public class ImageToBase64 {
    public static void main(String[] args) throws Exception {
        String imagePath = "/Users/wayan/tmp/photo-placeholder.png";

        byte[] fileContent = Files.readAllBytes(Paths.get(imagePath));
        String encodedString = Base64.getEncoder().encodeToString(fileContent);

        if (encodedString.length() > 65535) {
            System.out.println("Encoded string is too large");
        } else {
            System.out.println(encodedString);
        }
    }
}

Here are the first 200 characters of the generated base64 string:

iVBORw0KGgoAAAANSUhEUgAAAGQAAAB2CAYAAAA+/DbEAAAAAXNSR0IArs4c6QAAAIRlWElmTU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQA...

The size of a base64-encoded string could be significantly larger than the original file. It’s not always the best way to handle large files or in cases where you’re sensitive to data usage. To check the size of the generated string using the length() method of the String class.

As you can see in the code snippet above, the application will print “Encoded string is too large” if the base64 string of the image is larger than 65535 characters. Otherwise, it will print the base64 string

To use a Base64 encoded string with an HTML <img> tag, you can use the src attribute and specify the data as follows:

<img src="data:image/png;base64,iVBORw0..." alt="Your image description">

In this line:

  • data: is the Data URI scheme specifier.
  • image/png is the media type. This can be image/jpeg, image/gif, or other image types.
  • base64 indicates that the data is base64 encoded.
  • iVBORw0... is where your base64 data begins. Replace iVBORw0... with your base64 string.

You should replace image/png with the actual type of your image and replace the iVBORw0... part with your full Base64 string.

This approach allows you to inline small images directly into your HTML, reducing the number of HTTP requests. However, you should note that if images are large, this can increase the size of your HTML document and slow down load times. It might be more appropriate to use external image files for larger images.

Note that Base64 is not an encryption or hashing method, and should not be used for password or security purposes. It is a binary-to-text encoding schemes that represent binary data in an ASCII string format. It’s designed to be easily transmitted and stored while ensuring that the data remains intact without modification during transport.

How do I decode a Base64 encoded binary?

package org.kodejava.commons.codec;

import org.apache.commons.codec.binary.Base64;

import java.util.Arrays;

public class Base64Decode {
    public static void main(String[] args) {
        String hello = "SGVsbG8gV29ybGQ=";

        // Decode a previously encoded string using decodeBase64 method and
        // passing the byte[] of the encoded string.
        byte[] decoded = Base64.decodeBase64(hello.getBytes());

        // Print the decoded array
        System.out.println(Arrays.toString(decoded));

        // Convert the decoded byte[] back to the original string and print
        // the result.
        String decodedString = new String(decoded);
        System.out.println(hello + " = " + decodedString);
    }
}

The result of our code is:

[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
SGVsbG8gV29ybGQ= = Hello World

Maven Dependencies

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.16.0</version>
</dependency>

Maven Central