Base64 Decode Java — Руководство по getDecoder().decode()

·Backend Engineer·ПровереноAisha Osei·Опубликовано

Используйте бесплатный Base64 Decode Online прямо в браузере — установка не требуется.

Попробовать Base64 Decode Online онлайн →

Декодирование Base64 в Java — задача, к которой я обращаюсь практически каждый день: извлекаю секреты из переменных окружения Kubernetes, читаю бинарные пейлоады из REST API, инспектирую JWT-токены в ходе отладки. Встроенный класс java.util.Base64 (начиная с JDK 8) предоставляет три варианта декодера: getDecoder() для стандартного Base64, getUrlDecoder() для URL-безопасных входных данных и getMimeDecoder() для данных с переносами строк, таких как вложения электронной почты. Для быстрой одноразовой проверки без написания кода Base64-декодер ToolDeck обработает всё мгновенно прямо в браузере. Это руководство ориентировано на Java 8+ и охватывает все три декодера, потоковую обработку с wrap(InputStream), извлечение пейлоада JWT, декодирование файлов и ответов API, Apache Commons Codec как альтернативу и четыре ошибки, которые приводят к некорректному выводу в продакшне.

  • Base64.getDecoder().decode(s) — стандартный подход, встроен в java.util.Base64 начиная с JDK 8, зависимости не нужны.
  • Используйте getUrlDecoder() для JWT-токенов и OAuth-пейлоадов — они используют алфавит - и _, а не + и /.
  • getMimeDecoder() игнорирует переносы строк и пробелы, что делает его правильным выбором для вложений электронной почты и PEM-сертификатов.
  • decoder.wrap(InputStream) декодирует на лету для больших файлов, не загружая всё в память.
  • Базовый декодер работает в строгом режиме — завершающие переносы строк, пробелы или символы неправильного алфавита немедленно выбрасывают IllegalArgumentException.

Что такое декодирование Base64?

Кодирование Base64 преобразует бинарные данные в 64-символьное ASCII-представление, чтобы они могли безопасно передаваться через текстовые каналы — поля JSON, заголовки HTTP, документы XML, тела электронных писем. Декодирование выполняет обратное преобразование: каждые 4 символа Base64 преобразуются обратно в 3 исходных байта. Символ дополнения = в конце сигнализирует о том, сколько байт было добавлено для заполнения последней группы. Base64 — не шифрование: любой может его обратить. Его цель — безопасность передачи, а не конфиденциальность.

Типичные сценарии декодирования в Java: извлечение конфигурационных значений, переданных как переменные окружения в Base64, распаковка бинарного содержимого файлов из ответов облачных API, чтение PEM-кодированных сертификатов и инспекция пейлоадов JWT-токенов в процессе отладки.

Before · text
After · text
ZGItcHJvZC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbTo1NDMy
db-prod.us-east-1.amazonaws.com:5432

Base64.getDecoder().decode() — стандартный метод декодирования

Класс java.util.Base64 был добавлен в JDK 8 и заменил старый sun.misc.BASE64Decoder, на который все привыкли полагаться. Внешние зависимости не нужны — достаточно import java.util.Base64 и вызова Base64.getDecoder().decode(). Метод принимает String или byte[] и возвращает byte[] декодированных данных.

Минимальный рабочий пример

Java 8+
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class DecodeCredential {
    public static void main(String[] args) {
        // Kubernetes secret value, Base64-encoded
        String encoded = "ZGItcHJvZC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbTo1NDMy";

        byte[] decodedBytes = Base64.getDecoder().decode(encoded);
        String connectionString = new String(decodedBytes, StandardCharsets.UTF_8);

        System.out.println(connectionString);
        // db-prod.us-east-1.amazonaws.com:5432
    }
}

Всегда указывайте StandardCharsets.UTF_8 при создании строки. Конструктор new String(bytes) без аргументов использует кодировку платформы по умолчанию, которая различается между системами. На Windows-сервере с Cp1252 в качестве кодировки по умолчанию многобайтовые UTF-8 символы будут беззвучно искажаться.

Проверка обратного преобразования

Java 8+
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class RoundTrip {
    public static void main(String[] args) {
        String original = "redis://cache-prod.internal:6379/session-store";

        String encoded = Base64.getEncoder().encodeToString(
            original.getBytes(StandardCharsets.UTF_8)
        );
        System.out.println(encoded);
        // cmVkaXM6Ly9jYWNoZS1wcm9kLmludGVybmFsOjYzNzkvc2Vzc2lvbi1zdG9yZQ==

        byte[] decoded = Base64.getDecoder().decode(encoded);
        String recovered = new String(decoded, StandardCharsets.UTF_8);

        System.out.println(recovered.equals(original)); // true
    }
}

Декодирование в заранее выделенный буфер

Перегрузка с тремя аргументами decode(byte[] src, byte[] dst) записывает результат напрямую в буфер назначения и возвращает количество записанных байт. Это позволяет избежать лишнего выделения памяти на горячих путях выполнения:

Java 8+
import java.util.Base64;

public class DecodeToBuffer {
    public static void main(String[] args) {
        byte[] src = "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=".getBytes();
        byte[] dst = new byte[1024]; // pre-allocated

        int len = Base64.getDecoder().decode(src, dst);
        String result = new String(dst, 0, len);

        System.out.println(result);
        // {"host":"10.0.1.50","port":8443}
    }
}
Примечание:decode() выбрасывает IllegalArgumentException, если входные данные содержат символы вне алфавита Base64 (включая переносы строк и пробелы). Если входные данные могут содержать пробельные символы, переключитесь на getMimeDecoder() или очистите их с помощью encoded.strip() перед декодированием.

Декодирование Base64 в нестандартные типы и пользовательские объекты

Сырой byte[], возвращаемый decode(), часто нужно преобразовать во что-то более конкретное: UUID, сериализованный Java-объект, protobuf-сообщение или метку времени. Сам декодер всегда возвращает байты — преобразование в доменные типы лежит на вашей ответственности.

Base64 в UUID

Java 8+
import java.util.Base64;
import java.nio.ByteBuffer;
import java.util.UUID;

public class DecodeUUID {
    public static UUID fromBase64(String encoded) {
        byte[] bytes = Base64.getUrlDecoder().decode(encoded);
        ByteBuffer bb = ByteBuffer.wrap(bytes);
        return new UUID(bb.getLong(), bb.getLong());
    }

    public static void main(String[] args) {
        // Compact Base64-encoded UUID from an API response
        String encoded = "f47ac10b-58cc-4372-a567-0e02b2c3d479";
        UUID original = UUID.fromString(encoded);

        // Encode to Base64 (compact form — 22 chars vs 36)
        ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
        bb.putLong(original.getMostSignificantBits());
        bb.putLong(original.getLeastSignificantBits());
        String compact = Base64.getUrlEncoder().withoutPadding()
            .encodeToString(bb.array());
        System.out.println(compact); // 9HrBC1jMQ3KlZw4CssPUeQ

        // Decode back
        UUID recovered = fromBase64(compact);
        System.out.println(recovered); // f47ac10b-58cc-4372-a567-0e02b2c3d479
    }
}

Base64 в десериализованный JSON-объект с Jackson

Java 8+
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Instant;

public class DecodeJsonPayload {
    record DeployEvent(String service, String region, Instant deployedAt, int replicas) {}

    public static void main(String[] args) throws Exception {
        // Base64-encoded JSON payload from a message queue
        String encoded = "eyJzZXJ2aWNlIjoicGF5bWVudC1nYXRld2F5Iiwi"
            + "cmVnaW9uIjoiZXUtd2VzdC0xIiwiZGVwbG95ZWRBdCI6"
            + "IjIwMjYtMDMtMTVUMTQ6MzA6MDBaIiwicmVwbGljYXMiOjR9";

        byte[] jsonBytes = Base64.getDecoder().decode(encoded);
        String json = new String(jsonBytes, StandardCharsets.UTF_8);
        System.out.println(json);
        // {"service":"payment-gateway","region":"eu-west-1",
        //  "deployedAt":"2026-03-15T14:30:00Z","replicas":4}

        ObjectMapper mapper = new ObjectMapper();
        mapper.findAndRegisterModules(); // picks up JavaTimeModule
        DeployEvent event = mapper.readValue(jsonBytes, DeployEvent.class);

        System.out.println(event.service());   // payment-gateway
        System.out.println(event.deployedAt()); // 2026-03-15T14:30:00Z
    }
}
Предупреждение:Никогда не используйте ObjectInputStream для десериализации ненадёжных данных Base64. Атаки через механизм десериализации Java хорошо задокументированы — если закодированный контент поступает из внешнего источника, разбирайте его как JSON или protobuf вместо использования нативной Java-сериализации.

Справочник методов Base64.Decoder

Все методы принадлежат java.util.Base64 и его внутреннему классу Base64.Decoder. Три фабричных метода Base64 возвращают разные экземпляры декодера; методы decode() и wrap() находятся на экземпляре Decoder.

Метод
Возвращает
Тип входных данных
Описание
getDecoder()
Base64.Decoder
Стандартный декодер (RFC 4648 §4, алфавит + и / с дополнением =)
getUrlDecoder()
Base64.Decoder
URL-безопасный декодер (RFC 4648 §5, алфавит - и _ с дополнением =)
getMimeDecoder()
Base64.Decoder
MIME-декодер — игнорирует разделители строк и символы, не входящие в Base64
decode(String src)
byte[]
String
Декодирует входную строку в новый массив байт
decode(byte[] src)
byte[]
byte[]
Декодирует входной массив байт в новый массив байт
decode(byte[] src, byte[] dst)
int
byte[] + byte[]
Декодирует в заранее выделенный буфер dst, возвращает количество записанных байт
wrap(InputStream is)
InputStream
InputStream
Возвращает поток, декодирующий данные Base64 на лету

getMimeDecoder() — декодирование MIME и данных с переносами строк

Базовый декодер отклоняет всё, что выходит за пределы алфавита Base64 — в том числе переносы строк \r\n, которые всегда присутствуют в MIME-контенте. Вложения электронной почты, PEM-сертификаты и некоторые старые API-ответы переносят вывод Base64 каждые 76 символов. getMimeDecoder() беззвучно игнорирует разделители строк и любые символы вне алфавита Base64, обрабатывая это из коробки.

Java 8+
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class MimeDecode {
    public static void main(String[] args) {
        // PEM certificate body — line-wrapped at 76 characters
        String pemBody = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t\r\n"
            + "TUlJQm96Q0NBVWlnQXdJQkFnSUpBSXBhVDJU\r\n"
            + "aVFvZU1BMEdDU3FHU0liM0RRRU==";

        // getDecoder() would throw IllegalArgumentException here
        byte[] decoded = Base64.getMimeDecoder().decode(pemBody);
        System.out.println(new String(decoded, StandardCharsets.UTF_8));
        // -----BEGIN CERTIFICATE-----
        // MIIBozCCAUigAwIBAgIJAIpaT2T...
    }
}
Примечание:getMimeDecoder() работает в мягком режиме: он пропускает недопустимые символы вместо того, чтобы выбрасывать исключение. Для известных MIME-данных это нормально, но при произвольных входных данных он может беззвучно проглотить повреждение. Используйте getDecoder(), когда нужна строгая проверка.

Декодирование Base64 из файла и ответа API

Чтение файла в кодировке Base64 с диска

Бинарные файлы (изображения, сертификаты, зашифрованные блобы) иногда хранятся на диске в виде текста Base64. Прочитайте файл, декодируйте его и запишите бинарный результат:

Java 8+
import java.util.Base64;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class DecodeFile {
    public static void main(String[] args) {
        Path inputPath = Path.of("tls-cert.pem.b64");
        Path outputPath = Path.of("tls-cert.pem");

        try {
            String encoded = Files.readString(inputPath).strip();
            byte[] decoded = Base64.getMimeDecoder().decode(encoded);
            Files.write(outputPath, decoded);

            System.out.printf("Decoded %d bytes → %s%n", decoded.length, outputPath);
        } catch (IOException e) {
            System.err.println("File error: " + e.getMessage());
        } catch (IllegalArgumentException e) {
            System.err.println("Invalid Base64: " + e.getMessage());
        }
    }
}

Декодирование поля Base64 из ответа HTTP API

Облачные API (AWS KMS, GitHub Contents, Vault) часто возвращают бинарные данные в виде строк Base64 внутри JSON. Сначала разберите JSON, затем декодируйте нужное поле:

Java 11+
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class DecodeApiResponse {
    public static void main(String[] args) {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.example.com/secrets/db-password"))
            .header("Authorization", "Bearer sk-prod-9f8e7d6c")
            .build();

        try {
            HttpResponse<String> response = client.send(
                request, HttpResponse.BodyHandlers.ofString());

            if (response.statusCode() != 200) {
                System.err.printf("Unexpected status: %d%n", response.statusCode());
                return;
            }

            ObjectMapper mapper = new ObjectMapper();
            JsonNode root = mapper.readTree(response.body());

            // API returns: {"name":"db-password","value":"cG9zdGdyZXM6eGs5...","version":3}
            String encodedValue = root.get("value").asText();
            byte[] decoded = Base64.getDecoder().decode(encodedValue);
            String secret = new String(decoded, StandardCharsets.UTF_8);

            System.out.println("Secret: " + secret);
            // Secret: postgres:xk9mP2qR@db-prod:5432/orders
        } catch (Exception e) {
            System.err.println("Failed to fetch secret: " + e.getMessage());
        }
    }
}
Примечание:Оберните вызов decode в отдельный try-catch для IllegalArgumentException отдельно от сетевых ошибок. Смешение исключений ввода-вывода с ошибками декодирования усложняет отладку — вам нужно сразу понимать, вернул ли API некорректные данные или произошёл сетевой сбой.

Декодирование Base64 из командной строки

Не всегда нужна Java-программа. В любой системе Linux и macOS есть команда base64, а JDK 9+ поставляется с jshell для интерактивных однострочников на Java. При быстрой проверке в процессе отладки это быстрее, чем компилировать класс.

bash
# Decode a Base64 string (Linux / macOS)
echo "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=" | base64 --decode
# {"host":"10.0.1.50","port":8443}

# Decode and pretty-print with jq
echo "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=" | base64 --decode | jq .
# {
#   "host": "10.0.1.50",
#   "port": 8443
# }

# Quick decode with jshell (JDK 9+)
echo 'System.out.println(new String(java.util.Base64.getDecoder().decode("c2VydmVyLWNvbmZpZw==")))' | jshell -
# server-config

# macOS uses -D instead of --decode
echo "c2VydmVyLWNvbmZpZw==" | base64 -D

Для вставки закодированных строк прямо в браузер Base64-декодер ToolDeck поддерживает как стандартный, так и URL-безопасный варианты без какой-либо настройки.

Высокопроизводительная альтернатива: Apache Commons Codec

Встроенный java.util.Base64 уже хорошо оптимизирован — JDK 11+ использует интринсики x86 для кодирования и декодирования. Для большинства приложений нет причин тянуться к сторонней библиотеке. Тем не менее Apache Commons Codec остаётся популярным в унаследованных кодовых базах и предлагает Base64InputStream для потокового декодирования с автоматической обработкой пробельных символов.

XML (Maven)
<!-- pom.xml -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.17.0</version>
</dependency>
Java 8+
import org.apache.commons.codec.binary.Base64;

public class CommonsCodecDecode {
    public static void main(String[] args) {
        // Commons Codec is more lenient — handles whitespace and line breaks
        String encoded = "eyJob3N0IjoiMTAuMC4xLjUw\nIiwicG9ydCI6ODQ0M30=";
        byte[] decoded = Base64.decodeBase64(encoded);

        System.out.println(new String(decoded));
        // {"host":"10.0.1.50","port":8443}
    }
}

Главное преимущество Commons Codec перед встроенным API — мягкое отношение к пробельным символам по умолчанию и класс Base64InputStream, появившийся раньше decoder.wrap() из Java. Если вы используете Java 8+, встроенный API покрывает всё, что умеет Commons Codec. Я обращаюсь к Commons Codec только когда проект уже от него зависит.

Потоковая обработка больших файлов Base64 с decoder.wrap()

Загрузка файла Base64 размером 200 МБ через Files.readString() с последующим вызовом decode() выделяет около 350 МБ кучи: закодированная строка плюс декодированный массив байт. decoder.wrap(InputStream) декодирует на лету, сохраняя постоянное использование памяти.

Java 8+
import java.util.Base64;
import java.io.*;
import java.nio.file.*;

public class StreamDecode {
    public static void main(String[] args) throws IOException {
        Path src = Path.of("database-dump.sql.b64");
        Path dst = Path.of("database-dump.sql");

        try (InputStream in = Base64.getMimeDecoder().wrap(
                 new BufferedInputStream(Files.newInputStream(src)));
             OutputStream out = new BufferedOutputStream(Files.newOutputStream(dst))) {

            byte[] buffer = new byte[8192];
            int bytesRead;
            long total = 0;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
                total += bytesRead;
            }
            System.out.printf("Decoded %d bytes → %s%n", total, dst);
        }
    }
}

В Java 9+ можно заменить цикл чтения на in.transferTo(out) — то же самое с меньшим количеством кода. Используйте getMimeDecoder().wrap() вместо getDecoder().wrap(), если файл может содержать переносы строк (PEM-файлы, экспорты почты).

Java 9+
import java.util.Base64;
import java.io.*;
import java.nio.file.*;

public class StreamDecodeSimple {
    public static void main(String[] args) throws IOException {
        try (InputStream in = Base64.getMimeDecoder().wrap(
                 new BufferedInputStream(Files.newInputStream(Path.of("backup.tar.b64"))));
             OutputStream out = Files.newOutputStream(Path.of("backup.tar"))) {
            in.transferTo(out); // Java 9+
        }
    }
}
Предупреждение:getDecoder().wrap() не допускает переносов строк в потоке. Если данные Base64 содержат символы новой строки (перенос через каждые 76 символов), используйте getMimeDecoder().wrap() — иначе поток беззвучно производит повреждённый вывод или выбрасывает исключение в непредсказуемой позиции чтения.

Декодирование пейлоада JWT в Java без JWT-библиотеки

JWT состоит из трёх сегментов, закодированных в Base64url и разделённых точками. Средний сегмент — это пейлоад, который вас интересует при отладке. Его можно декодировать без подключения jjwt или Nimbus. Разбейте токен по ., декодируйте вторую часть с помощью getUrlDecoder() и разберите полученный JSON:

Java 8+
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class JWTInspect {
    public static String decodeJwtPayload(String token) {
        String[] parts = token.split("\\.");
        if (parts.length != 3) {
            throw new IllegalArgumentException(
                "Invalid JWT: expected 3 segments, got " + parts.length);
        }
        // JWT uses URL-safe Base64 without padding
        byte[] payload = Base64.getUrlDecoder().decode(parts[1]);
        return new String(payload, StandardCharsets.UTF_8);
    }

    public static void main(String[] args) {
        String token = "eyJhbGciOiJSUzI1NiJ9"
            + ".eyJzdWIiOiJ1c3ItNjcyIiwiaXNzIjoiYXV0aC5leGFtcGxlLmNvbSIs"
            + "ImV4cCI6MTc0MTk1NjgwMCwicm9sZXMiOlsiYWRtaW4iLCJiaWxsaW5nIl19"
            + ".SIGNATURE_PLACEHOLDER";

        String payload = decodeJwtPayload(token);
        System.out.println(payload);
        // {"sub":"usr-672","iss":"auth.example.com",
        //  "exp":1741956800,"roles":["admin","billing"]}
    }
}

Распространённые ошибки

Я сталкивался с каждой из них на ревью кода, и первые две составляют подавляющее большинство связанных с Base64 ошибок в продакшн-сервисах на Java.

Использование getDecoder() для URL-безопасных входных данных

Проблема: JWT-токены и токены доступа OAuth используют URL-безопасный алфавит (- и _). Передача их в getDecoder() выбрасывает IllegalArgumentException, поскольку - отсутствует в стандартном алфавите Base64.

Решение: Проверьте источник данных: токены из систем аутентификации требуют getUrlDecoder(); MIME-вложения требуют getMimeDecoder().

Before · Java
After · Java
// JWT header — URL-safe, no padding
String header = "eyJhbGciOiJSUzI1NiJ9";
byte[] decoded = Base64.getDecoder().decode(header);
// IllegalArgumentException: Illegal base64 character 2d
String header = "eyJhbGciOiJSUzI1NiJ9";
byte[] decoded = Base64.getUrlDecoder().decode(header);
System.out.println(new String(decoded));
// {"alg":"RS256"}
Не указана кодировка при создании String

Проблема: new String(bytes) использует кодировку JVM по умолчанию, которая различается между окружениями. Linux CI-сервер (UTF-8) и Windows production-хост (Cp1252) дают разные результаты для одних и тех же байт.

Решение: Всегда передавайте StandardCharsets.UTF_8 вторым аргументом.

Before · Java
After · Java
byte[] decoded = Base64.getDecoder().decode(encoded);
String result = new String(decoded);
// platform-dependent — may corrupt multi-byte characters
byte[] decoded = Base64.getDecoder().decode(encoded);
String result = new String(decoded, StandardCharsets.UTF_8);
// consistent across all platforms
Декодирование строки с завершающими пробельными символами

Проблема: Строки Base64, скопированные из терминала или прочитанные из конфигурационных файлов, часто имеют завершающие переносы строк. Базовый декодер отклоняет любой символ вне алфавита Base64.

Решение: Вызовите .strip() для входных данных перед декодированием или переключитесь на getMimeDecoder(), который игнорирует пробельные символы.

Before · Java
After · Java
// Read from environment variable — has a trailing newline
String encoded = System.getenv("DB_PASSWORD_B64"); // "cG9zdGdyZXM=
"
byte[] decoded = Base64.getDecoder().decode(encoded);
// IllegalArgumentException: Illegal base64 character a
String encoded = System.getenv("DB_PASSWORD_B64");
byte[] decoded = Base64.getDecoder().decode(encoded.strip());
System.out.println(new String(decoded, StandardCharsets.UTF_8));
// postgres
Преобразование бинарных данных в String

Проблема: Вызов new String(decoded) для бинарного контента (изображения, protobuf, зашифрованные блобы) создаёт некорректную строку. Обратное преобразование в байты впоследствии беззвучно повреждает данные, поскольку конструктор String заменяет недопустимые UTF-8 последовательности.

Решение: Сохраняйте бинарные данные как byte[] на протяжении всего пайплайна. Преобразуйте в String только когда точно знаете, что контент является текстом.

Before · Java
After · Java
byte[] decoded = Base64.getDecoder().decode(pngBase64);
String imageStr = new String(decoded); // corrupts binary
Files.writeString(Path.of("image.png"), imageStr); // broken file
byte[] decoded = Base64.getDecoder().decode(pngBase64);
// Write bytes directly — no String conversion
Files.write(Path.of("image.png"), decoded);

Сравнение методов

Встроенные декодеры покрывают большинство случаев. Apache Commons Codec и Guava — альтернативы, которые можно встретить в более старых кодовых базах.

Метод
Вариант кодировки
Игнорирует пробелы
Потоковый
Пользовательские типы
Требует установки
Base64.getDecoder()
Стандартный (+, /)
Нет (JDK 8+)
Base64.getUrlDecoder()
URL-безопасный (-, _)
Нет (JDK 8+)
Base64.getMimeDecoder()
MIME (переносы строк допустимы)
Нет (JDK 8+)
decoder.wrap(InputStream)
Любой вариант
Зависит от декодера
Нет (JDK 8+)
Apache Commons Base64InputStream
Стандартный / URL-безопасный
Да (commons-codec)
Apache Commons Base64.decodeBase64()
Стандартный
Да (commons-codec)
Guava BaseEncoding.base64().decode()
Стандартный
Да (guava)

Для JWT-токенов и современных API-пейлоадов: getUrlDecoder(). Для вложений электронной почты и PEM-сертификатов: getMimeDecoder(). Для больших файлов, где важна память: decoder.wrap(InputStream). Для всего остального: getDecoder(). Apache Commons Codec имеет смысл только если он уже есть в дереве зависимостей.

Для быстрой проверки в процессе разработки онлайн-декодер Base64 быстрее, чем писать одноразовый класс.

Часто задаваемые вопросы

Как декодировать строку Base64 в Java?

Импортируйте java.util.Base64 и вызовите Base64.getDecoder().decode(encodedString). Метод возвращает byte[] — оберните результат в new String(bytes, StandardCharsets.UTF_8), чтобы получить читаемый текст. Для URL-безопасного Base64 (используется в JWT) замените getDecoder() на getUrlDecoder().

Java 8+
import java.util.Base64;
import java.nio.charset.StandardCharsets;

byte[] decoded = Base64.getDecoder().decode("c2VydmVyLWNvbmZpZw==");
String result = new String(decoded, StandardCharsets.UTF_8);
System.out.println(result); // server-config

В чём разница между getDecoder() и getMimeDecoder() в Java?

getDecoder() работает в строгом режиме — он отклоняет любой символ вне алфавита Base64, включая переносы строк. getMimeDecoder() допускает разделители строк (\r\n) и игнорирует любые символы, не входящие в Base64, что делает его правильным выбором для декодирования вложений электронной почты и PEM-сертификатов, в которых данные переносятся каждые 76 символов.

Java 8+
String wrapped = "c2VydmVyLWNv\r\nbmZpZw==";

// getDecoder() throws IllegalArgumentException
// Base64.getDecoder().decode(wrapped); // FAILS

// getMimeDecoder() handles it
byte[] decoded = Base64.getMimeDecoder().decode(wrapped);
System.out.println(new String(decoded)); // server-config

Как декодировать URL-безопасную строку Base64 в Java?

Используйте Base64.getUrlDecoder().decode(encoded). URL-декодер ожидает алфавит - и _, определённый в RFC 4648 §5, а не + и /. Токены JWT всегда используют этот алфавит. Если символы дополнения (=) были удалены (стандартная практика в JWT), URL-декодер всё равно справится — он принимает как дополненные, так и недополненные входные данные.

Java 8+
import java.util.Base64;

// JWT header — URL-safe, no padding
String jwtHeader = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
byte[] decoded = Base64.getUrlDecoder().decode(jwtHeader);
System.out.println(new String(decoded));
// {"alg":"HS256","typ":"JWT"}

Как потоково декодировать большой файл Base64 в Java?

Используйте decoder.wrap(inputStream), обернув FileInputStream. Возвращаемый InputStream декодирует Base64 на лету по мере чтения байт, поэтому использование памяти остаётся постоянным независимо от размера файла. Пропустите его через BufferedInputStream или сразу в Files.copy() для максимальной производительности.

Java 8+
import java.util.Base64;
import java.io.*;
import java.nio.file.*;

try (InputStream in = Base64.getDecoder().wrap(
        new BufferedInputStream(new FileInputStream("payload.b64")));
     OutputStream out = new FileOutputStream("payload.bin")) {
    in.transferTo(out);
}

Почему Base64.getDecoder().decode() выбрасывает IllegalArgumentException?

Базовый декодер работает в строгом режиме: он отклоняет переносы строк, пробелы и любой символ вне диапазона A-Za-z0-9+/=. Три распространённые причины: у входной строки есть завершающий перенос строки (обрежьте его), строка использует URL-безопасные символы - и _ (переключитесь на getUrlDecoder()), или строка переносится каждые 76 символов (переключитесь на getMimeDecoder()). Если сообщение об ошибке непонятно, проверьте сырые байты.

Java 8+
String raw = "c2VydmVyLWNvbmZpZw==\n"; // trailing newline

// Option 1: trim whitespace
byte[] decoded = Base64.getDecoder().decode(raw.strip());

// Option 2: use MIME decoder which ignores whitespace
byte[] decoded2 = Base64.getMimeDecoder().decode(raw);

Можно ли декодировать Base64 в Java без java.util.Base64?

Да, но на Java 8+ нет никаких причин это делать. До Java 8 разработчики использовали sun.misc.BASE64Decoder (внутренний, удалён в Java 9+), javax.xml.bind.DatatypeConverter.parseBase64Binary() (удалён в Java 11) или Apache Commons Codec. Все три варианта либо устарели, либо требуют дополнительной зависимости. Используйте java.util.Base64 — он быстрее, входит в состав JDK и охватывает все три варианта (базовый, URL-безопасный, MIME).

Связанные инструменты

  • Base64 Encoder — кодируйте текст или бинарные данные в Base64 прямо в браузере, удобно для генерации тестовых данных для вставки в юнит-тесты на Java.
  • JWT Decoder — разбивает и декодирует все три сегмента JWT сразу, с пошаговой инспекцией полей пейлоада — быстрее, чем писать Java-класс, когда нужно просто прочитать токен.
  • URL Decoder — декодирует percent-encoded строки, полезно когда ответы API сочетают данные Base64url с percent-encoded параметрами запроса.
  • JSON Formatter — после декодирования пейлоада JWT в Base64 или конфига API вставьте JSON сюда, чтобы красиво отформатировать и проверить структуру.
Также доступно на:JavaScriptPythonGoC#
PN
Pavel NovakBackend Engineer

Pavel is a backend engineer with deep roots in the JVM ecosystem, working primarily with Java and Kotlin. He has extensive experience building data-intensive services and integrating third-party APIs at scale. He writes about modern Java features, the Jackson ecosystem, serialisation patterns, and practical approaches to keeping large codebases maintainable.

AO
Aisha OseiТехнический рецензент

Aisha is a Java engineer specialising in application security, Spring Security, and API design. She has worked on identity and access management systems, OAuth 2.0 integrations, and microservice security at scale. She writes about secure Java coding practices, token validation, cryptographic utilities, and the Spring ecosystem from a security-first perspective.