Skip to content

Base64 Encode / Decode — Java source

Encode text to Base64 or decode it back. UTF-8 safe, runs entirely in your browser, with a shareable link to your exact input.

This is the Java implementation — the same logic the interactive tool runs, in a shareable, citable form.

// base64 — UTF-8 safe Base64 encode/decode.
//
// Language: Java (17+, standard library only — java.util.Base64 is the
//           RFC 4648 codec, the same role the base64 module plays in this
//           tool's python.py)
// Source:   CosmoDev polyglot showcase port of the `base64` tool, ported
//           from src/lib/base64.ts (the canonical TypeScript implementation).
// License:  display source — part of CosmoDev's polyglot tool pages.
//
// Two details keep the stdlib route faithful to the TS contract:
//   - whitespace is stripped with the same \s+ regex the TS port uses before
//     decoding, so line-wrapped Base64 decodes cleanly;
//   - decoded bytes must form valid UTF-8: new String(bytes, UTF_8) would
//     silently substitute U+FFFD, so decoding runs through a CharsetDecoder
//     with REPORT actions instead.
//
// Run: java java.java   (single-file source launch, Java 11+)

import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

final class Base64Tool {

    /** Encode a Unicode string to standard (padded) Base64 over its UTF-8 bytes. */
    static String b64encode(String text) {
        return Base64.getEncoder().encodeToString(
                text.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * Decode standard Base64 back to the original Unicode text.
     *
     * Whitespace is stripped first (the TS port's \s+ regex), so line-wrapped
     * Base64 decodes cleanly. java.util.Base64 then rejects illegal characters
     * and bad padding with IllegalArgumentException — rethrown with a stable
     * message — and decoded bytes that are not valid UTF-8 fail the same way.
     * This matches the TS port's "throw on invalid input" contract.
     */
    static String b64decode(String b64) {
        String cleaned = b64.replaceAll("\\s+", "");

        byte[] raw;
        try {
            raw = Base64.getDecoder().decode(cleaned);
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(
                    "invalid Base64 input: " + e.getMessage(), e);
        }

        try {
            return StandardCharsets.UTF_8.newDecoder()
                    .onMalformedInput(CodingErrorAction.REPORT)
                    .onUnmappableCharacter(CodingErrorAction.REPORT)
                    .decode(ByteBuffer.wrap(raw))
                    .toString();
        } catch (CharacterCodingException e) {
            throw new IllegalArgumentException(
                    "decoded bytes are not valid UTF-8", e);
        }
    }

    public static void main(String[] args) {
        System.out.println(b64encode("Hello, world!"));        // SGVsbG8sIHdvcmxkIQ==
        System.out.println(b64decode("aGVs\nbG8g d29ybGQ=")); // hello world
        System.out.println(b64decode(b64encode("héllo 🌍")));  // multi-byte UTF-8 survives

        try {
            b64decode("SGVsbG8*");
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }

        // "/w==" decodes to the single byte 0xFF, which is not valid UTF-8.
        try {
            b64decode("/w==");
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
    }
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →