Dekodowanie Base64 w Javie to coś, po co sięgam co kilka dni — wyciągam sekrety ze zmiennych środowiskowych Kubernetes, odczytuję binarne payloady z REST API, podglądam tokeny JWT podczas sesji debugowania. Wbudowana klasa java.util.Base64 (od JDK 8) dostarcza trzy warianty dekodera: getDecoder() dla standardowego Base64, getUrlDecoder() dla danych bezpiecznych dla URL oraz getMimeDecoder() dla danych z zawijaniem linii, takich jak załączniki e-mail. Jeśli chcesz sprawdzić coś od ręki bez pisania kodu, dekoder Base64 ToolDeck obsłuży to natychmiast w przeglądarce. Ten przewodnik jest przeznaczony dla Java 8+ i omawia wszystkie trzy dekodery, strumieniowanie z wrap(InputStream), wyodrębnianie payloadów JWT, dekodowanie plików i odpowiedzi API, Apache Commons Codec jako alternatywę oraz cztery błędy, które generują uszkodzone dane na produkcji.
- ✓Base64.getDecoder().decode(s) to standardowe podejście — wbudowane w java.util.Base64 od JDK 8, bez żadnych zależności.
- ✓Użyj getUrlDecoder() dla tokenów JWT i payloadów OAuth — używają alfabetu z - i _, a nie + i /.
- ✓getMimeDecoder() ignoruje łamania linii i białe znaki, przez co jest właściwym wyborem dla załączników e-mail i certyfikatów PEM.
- ✓decoder.wrap(InputStream) dekoduje w locie duże pliki bez ładowania wszystkiego do pamięci.
- ✓Podstawowy dekoder jest rygorystyczny — końcowe nowe linie, spacje lub znaki złego alfabetu od razu rzucają IllegalArgumentException.
Czym jest dekodowanie Base64?
Kodowanie Base64 konwertuje dane binarne na reprezentację ASCII złożoną z 64 znaków, dzięki czemu mogą bezpiecznie przechodzić przez kanały obsługujące tylko tekst — pola JSON, nagłówki HTTP, dokumenty XML, treści e-mail. Dekodowanie odwraca ten proces: każde 4 znaki Base64 mapują się z powrotem na 3 oryginalne bajty. Dopełnienie = na końcu sygnalizuje, ile bajtów zostało dodanych do wypełnienia ostatniej grupy. Base64 to nie szyfrowanie — każdy może je odwrócić. Jego celem jest bezpieczeństwo transportu, a nie tajność danych.
Typowe scenariusze dekodowania w Javie: wyodrębnianie wartości konfiguracji wstrzyknietych jako zmienne środowiskowe zakodowane Base64, rozpakowywanie binarnej zawartości pliku z odpowiedzi API chmury, odczytywanie certyfikatów zakodowanych w PEM oraz podgląd payloadów tokenów JWT podczas debugowania.
ZGItcHJvZC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbTo1NDMy
db-prod.us-east-1.amazonaws.com:5432
Base64.getDecoder().decode() — standardowa metoda dekodowania
Klasa java.util.Base64 została dodana w JDK 8 i zastąpiła stary sun.misc.BASE64Decoder, na którym wszyscy polegali. Żadne zewnętrzne zależności nie są potrzebne — wystarczy import java.util.Base64 i wywołanie Base64.getDecoder().decode(). Metoda przyjmuje String lub byte[] i zwraca byte[] zdekodowanych danych.
Minimalny działający przykład
import java.util.Base64;
import java.nio.charset.StandardCharsets;
public class DecodeCredential {
public static void main(String[] args) {
// Wartość sekretu Kubernetes zakodowana Base64
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
}
}Zawsze podawaj StandardCharsets.UTF_8 podczas tworzenia obiektu String. Konstruktor new String(bytes) bez argumentów używa domyślnego kodowania platformy, które różni się między systemami. Na serwerze Windows z Cp1252 jako domyślnym, wielobajtowe znaki UTF-8 zostaną cicho uszkodzone.
Weryfikacja przez round-trip
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
}
}Dekodowanie do wcześniej zaalokowanego bufora
Przeciążona metoda decode(byte[] src, byte[] dst) z trzema argumentami zapisuje wynik bezpośrednio do bufora docelowego i zwraca liczbę zapisanych bajtów. Pozwala to uniknąć dodatkowej alokacji na gorących ścieżkach wykonania:
import java.util.Base64;
public class DecodeToBuffer {
public static void main(String[] args) {
byte[] src = "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=".getBytes();
byte[] dst = new byte[1024]; // wcześniej zaalokowany
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() rzuca IllegalArgumentException, jeśli dane wejściowe zawierają znaki spoza alfabetu Base64 (w tym łamania linii i spacje). Jeśli dane wejściowe mogą zawierać białe znaki, przełącz się na getMimeDecoder() lub usuń je metodą encoded.strip() przed dekodowaniem.Dekodowanie Base64 z niestandardowymi typami i obiektami
Surowy byte[] zwrócony przez decode() często musi zostać przekształcony w coś bardziej konkretnego: UUID, zserializowany obiekt Java, komunikat protobuf lub znacznik czasu. Dekoder zawsze zwraca bajty — konwersja na typy domenowe należy do Ciebie.
Base64 do UUID
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) {
// Kompaktowy UUID zakodowany Base64 z odpowiedzi API
String encoded = "f47ac10b-58cc-4372-a567-0e02b2c3d479";
UUID original = UUID.fromString(encoded);
// Zakoduj do Base64 (postać kompaktowa — 22 znaki 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
// Zdekoduj z powrotem
UUID recovered = fromBase64(compact);
System.out.println(recovered); // f47ac10b-58cc-4372-a567-0e02b2c3d479
}
}Base64 do zdeserializowanego obiektu JSON z Jacksonem
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 {
// Payload JSON zakodowany Base64 z kolejki komunikatów
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 do deserializacji niezaufanych danych Base64. Ataki przez deserializację Java są dobrze udokumentowane — jeśli zakodowana zawartość pochodzi z zewnętrznego źródła, przetwarzaj ją jako JSON lub protobuf zamiast korzystać z natywnej serializacji Java.Dokumentacja metod Base64.Decoder
Wszystkie metody należą do java.util.Base64 i jego klasy wewnętrznej Base64.Decoder. Trzy metody fabryczne klasy Base64 zwracają różne instancje dekoderów; metody decode() i wrap() są dostępne na instancji Decoder.
getMimeDecoder() — dekodowanie danych MIME z zawijaniem linii
Podstawowy dekoder odrzuca wszystko spoza alfabetu Base64 — a to obejmuje też łamania linii \r\n, które zawierają zawsze dane zakodowane w MIME. Załączniki e-mail, certyfikaty PEM i niektóre starsze odpowiedzi API zawijają dane Base64 co 76 znaków na linię. getMimeDecoder() cicho ignoruje separatory linii i wszelkie znaki spoza alfabetu Base64, więc obsługuje to natywnie.
import java.util.Base64;
import java.nio.charset.StandardCharsets;
public class MimeDecode {
public static void main(String[] args) {
// Treść certyfikatu PEM — zawijana co 76 znaków
String pemBody = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t\r\n"
+ "TUlJQm96Q0NBVWlnQXdJQkFnSUpBSXBhVDJU\r\n"
+ "aVFvZU1BMEdDU3FHU0liM0RRRU==";
// getDecoder() rzuciłby IllegalArgumentException
byte[] decoded = Base64.getMimeDecoder().decode(pemBody);
System.out.println(new String(decoded, StandardCharsets.UTF_8));
// -----BEGIN CERTIFICATE-----
// MIIBozCCAUigAwIBAgIJAIpaT2T...
}
}getMimeDecoder() jest liberalny: pomija nieprawidłowe znaki zamiast rzucać wyjątek. To jest w porządku dla znanych danych MIME, ale może cicho przełknąć uszkodzenia w dowolnych danych wejściowych. Używaj getDecoder(), gdy potrzebujesz rygorystycznej walidacji.Dekodowanie Base64 z pliku i odpowiedzi API
Odczytywanie pliku zakodowanego Base64 z dysku
Pliki binarne (obrazy, certyfikaty, zaszyfrowane bloki danych) są niekiedy przechowywane na dysku jako tekst Base64. Odczytaj plik, zdekoduj, zapisz dane binarne:
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());
}
}
}Dekodowanie pola Base64 z odpowiedzi HTTP API
Chmurowe API (AWS KMS, GitHub Contents, Vault) często zwracają dane binarne jako ciągi Base64 wewnątrz JSON. Najpierw sparsuj JSON, a następnie zdekoduj docelowe pole:
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 zwraca: {"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());
}
}
}IllegalArgumentException oddzielnie od błędów sieciowych. Mieszanie wyjątków I/O z błędami dekodowania utrudnia debugowanie — chcesz od razu wiedzieć, czy API zwróciło nieprawidłowe dane, czy sieć zawiodła.Dekodowanie Base64 z wiersza poleceń
Nie zawsze potrzebujesz programu w Javie. Każdy system Linux i macOS ma polecenie base64, a JDK 9+ dostarcza jshell dla interaktywnych jednolinijkowców Java. Przy szybkim podglądzie podczas debugowania jest to szybsze niż kompilowanie klasy.
# Dekodowanie ciągu Base64 (Linux / macOS)
echo "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=" | base64 --decode
# {"host":"10.0.1.50","port":8443}
# Dekodowanie i formatowanie z jq
echo "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=" | base64 --decode | jq .
# {
# "host": "10.0.1.50",
# "port": 8443
# }
# Szybkie dekodowanie z jshell (JDK 9+)
echo 'System.out.println(new String(java.util.Base64.getDecoder().decode("c2VydmVyLWNvbmZpZw==")))' | jshell -
# server-config
# macOS używa -D zamiast --decode
echo "c2VydmVyLWNvbmZpZw==" | base64 -DJeśli chcesz wkleić zakodowane ciągi bezpośrednio w przeglądarce, dekoder Base64 ToolDeck obsługuje zarówno wariant standardowy, jak i bezpieczny dla URL bez żadnej konfiguracji.
Wydajna alternatywa: Apache Commons Codec
Wbudowana klasa java.util.Base64 jest już dobrze zoptymalizowana — JDK 11+ używa intrinsics na x86 przy kodowaniu i dekodowaniu. W większości aplikacji nie ma powodu, aby sięgać po bibliotekę zewnętrzną. Niemniej Apache Commons Codec pozostaje popularny w starszych bazach kodu i oferuje Base64InputStream do strumieniowego dekodowania z automatyczną obsługą białych znaków.
<!-- pom.xml -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.17.0</version>
</dependency>import org.apache.commons.codec.binary.Base64;
public class CommonsCodecDecode {
public static void main(String[] args) {
// Commons Codec jest bardziej liberalny — obsługuje białe znaki i łamania linii
String encoded = "eyJob3N0IjoiMTAuMC4xLjUw\nIiwicG9ydCI6ODQ0M30=";
byte[] decoded = Base64.decodeBase64(encoded);
System.out.println(new String(decoded));
// {"host":"10.0.1.50","port":8443}
}
}Główną zaletą Commons Codec nad wbudowanym API jest domyślna tolerancja dla białych znaków oraz klasa Base64InputStream, która powstała przed Java's decoder.wrap(). Jeśli używasz Java 8+, wbudowane API pokrywa wszystko, co oferuje Commons Codec. Po Commons Codec sięgam tylko wtedy, gdy projekt już na nim polega.
Strumieniowe przetwarzanie dużych plików Base64 z decoder.wrap()
Załadowanie pliku Base64 o rozmiarze 200 MB za pomocą Files.readString()i wywołanie decode() alokuje ok. 350 MB sterty: zakodowany ciąg plus zdekodowana tablica bajtów. decoder.wrap(InputStream) dekoduje w locie, utrzymując stałe zużycie pamięci.
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);
}
}
}Na Java 9+ możesz zastąpić pętlę odczytu wywołaniem in.transferTo(out) — robi to samo przy mniejszej ilości kodu. Użyj getMimeDecoder().wrap() zamiast getDecoder().wrap(), jeśli plik może zawierać łamania linii (pliki PEM, eksporty e-mail).
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() nie toleruje łamań linii w strumieniu. Jeśli dane Base64 zawierają znaki nowej linii (zawijane co 76 znaków), użyj getMimeDecoder().wrap() — w przeciwnym razie strumień cicho produkuje uszkodzone dane lub rzuca wyjątek w nieprzewidywalnej pozycji odczytu.Dekodowanie payloadu JWT zakodowanego Base64 w Javie bez biblioteki JWT
Token JWT to trzy segmenty zakodowane Base64url połączone kropkami. Środkowy segment to payload — ta część, na której zależy nam podczas debugowania. Można go zdekodować bez dodawania jjwt ani Nimbus. Podziel po ., zdekoduj drugi fragment za pomocą getUrlDecoder() i sparsuj wynikowy JSON:
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 używa Base64 bezpiecznego dla URL bez dopełnienia
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"]}
}
}Typowe błędy
Spotkałem każdy z tych błędów podczas przeglądów kodu, a pierwsze dwa odpowiadają za zdecydowaną większość błędów produkcyjnych związanych z Base64 w serwisach Java.
Problem: Tokeny JWT i tokeny dostępu OAuth używają alfabetu bezpiecznego dla URL (- i _). Przekazanie ich do getDecoder() rzuca IllegalArgumentException, ponieważ - nie należy do standardowego alfabetu Base64.
Rozwiązanie: Sprawdź źródło danych: tokeny z systemów uwierzytelniania wymagają getUrlDecoder(); załączniki MIME wymagają getMimeDecoder().
// Nagłówek JWT — URL-safe, bez dopełnienia 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"}Problem: new String(bytes) używa domyślnego zestawu znaków JVM, który różni się między środowiskami. Serwer CI na Linuksie (UTF-8) i host produkcyjny na Windows (Cp1252) dają różne wyniki dla tych samych bajtów.
Rozwiązanie: Zawsze przekazuj StandardCharsets.UTF_8 jako drugi argument.
byte[] decoded = Base64.getDecoder().decode(encoded); String result = new String(decoded); // zależny od platformy — może uszkodzić znaki wielobajtowe
byte[] decoded = Base64.getDecoder().decode(encoded); String result = new String(decoded, StandardCharsets.UTF_8); // spójny na wszystkich platformach
Problem: Ciągi Base64 wklejone z terminala lub odczytane z plików konfiguracyjnych często mają końcowe znaki nowej linii. Podstawowy dekoder odrzuca każdy znak spoza alfabetu Base64.
Rozwiązanie: Wywołaj .strip() na danych wejściowych przed dekodowaniem lub przełącz się na getMimeDecoder(), który ignoruje białe znaki.
// Odczytano ze zmiennej środowiskowej — ma końcową nową linię
String encoded = System.getenv("DB_PASSWORD_B64"); // "cG9zdGdyZXM=
"
byte[] decoded = Base64.getDecoder().decode(encoded);
// IllegalArgumentException: Illegal base64 character aString encoded = System.getenv("DB_PASSWORD_B64");
byte[] decoded = Base64.getDecoder().decode(encoded.strip());
System.out.println(new String(decoded, StandardCharsets.UTF_8));
// postgresProblem: Wywołanie new String(decoded) na danych binarnych (obrazy, protobuf, zaszyfrowane bloki) tworzy nieprawidłowy String. Późniejsza konwersja z powrotem do bajtów cicho uszkadza dane, ponieważ konstruktor String zastępuje nieprawidłowe sekwencje UTF-8.
Rozwiązanie: Trzymaj dane binarne jako byte[] przez cały pipeline. Konwertuj do String tylko wtedy, gdy wiesz, że zawartość jest tekstem.
byte[] decoded = Base64.getDecoder().decode(pngBase64);
String imageStr = new String(decoded); // niszczy dane binarne
Files.writeString(Path.of("image.png"), imageStr); // uszkodzony plikbyte[] decoded = Base64.getDecoder().decode(pngBase64);
// Zapisz bajty bezpośrednio — bez konwersji do String
Files.write(Path.of("image.png"), decoded);Porównanie metod
Wbudowane dekodery pokrywają większość przypadków użycia. Apache Commons Codec i Guava to alternatywy, które możesz spotkać w starszych bazach kodu.
Dla tokenów JWT i nowoczesnych payloadów API: getUrlDecoder(). Dla załączników e-mail i certyfikatów PEM: getMimeDecoder(). Dla dużych plików, gdzie liczy się pamięć: decoder.wrap(InputStream). Dla wszystkiego innego: getDecoder(). Apache Commons Codec ma sens tylko wtedy, gdy jest już w drzewie zależności projektu.
Przy szybkiej weryfikacji podczas developmentu, internetowy dekoder Base64 jest szybszy niż pisanie jednorazowej klasy.
Często zadawane pytania
Jak zdekodować ciąg Base64 w Javie?
Zaimportuj java.util.Base64 i wywołaj Base64.getDecoder().decode(encodedString). Metoda zwraca byte[] — owiń wynik konstruktorem new String(bytes, StandardCharsets.UTF_8), aby otrzymać czytelny tekst. Dla Base64 bezpiecznego dla URL (stosowanego w tokenach JWT) zamień getDecoder() na getUrlDecoder().
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-configJaka jest różnica między getDecoder() a getMimeDecoder() w Javie?
getDecoder() jest rygorystyczny — odrzuca każdy znak spoza alfabetu Base64, łącznie z łamaniami linii. getMimeDecoder() toleruje separatory linii (\r\n) i ignoruje znaki spoza alfabetu Base64, przez co jest właściwym wyborem przy dekodowaniu załączników e-mail i certyfikatów PEM, gdzie dane są zawijane co 76 znaków.
String wrapped = "c2VydmVyLWNv\r\nbmZpZw=="; // getDecoder() rzuca IllegalArgumentException // Base64.getDecoder().decode(wrapped); // FAILS // getMimeDecoder() radzi sobie z tym byte[] decoded = Base64.getMimeDecoder().decode(wrapped); System.out.println(new String(decoded)); // server-config
Jak zdekodować ciąg Base64 bezpieczny dla URL w Javie?
Użyj Base64.getUrlDecoder().decode(encoded). Dekoder URL oczekuje alfabetu - i _ zdefiniowanego w RFC 4648 §5, a nie + i /. Tokeny JWT zawsze używają tego alfabetu. Jeśli znaki dopełnienia (=) zostały usunięte (powszechne w tokenach JWT), dekoder URL nadal sobie z tym radzi — Java akceptuje zarówno dane z dopełnieniem, jak i bez.
import java.util.Base64;
// Nagłówek JWT — URL-safe, bez dopełnienia
String jwtHeader = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
byte[] decoded = Base64.getUrlDecoder().decode(jwtHeader);
System.out.println(new String(decoded));
// {"alg":"HS256","typ":"JWT"}Jak strumieniowo dekodować duży plik Base64 w Javie?
Użyj decoder.wrap(inputStream), aby opakować FileInputStream. Zwrócony InputStream dekoduje Base64 w locie podczas odczytu bajtów, więc zużycie pamięci jest stałe niezależnie od rozmiaru pliku. Przekieruj go przez BufferedInputStream lub bezpośrednio do Files.copy() dla najlepszej przepustowości.
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);
}Dlaczego Base64.getDecoder().decode() rzuca IllegalArgumentException?
Podstawowy dekoder jest rygorystyczny: odrzuca łamania linii, spacje i wszelkie znaki spoza A-Za-z0-9+/=. Trzy częste przyczyny: dane wejściowe mają końcowe znaki nowej linii (usuń je metodą trim), dane używają znaków bezpiecznych dla URL jak - i _ (zmień na getUrlDecoder()), lub dane były zawijane co 76 znaków (zmień na getMimeDecoder()). Zawsze sprawdź surowe bajty, gdy komunikat błędu jest nieczytelny.
String raw = "c2VydmVyLWNvbmZpZw==\n"; // końcowa nowa linia // Opcja 1: usuń białe znaki byte[] decoded = Base64.getDecoder().decode(raw.strip()); // Opcja 2: użyj dekodera MIME, który ignoruje białe znaki byte[] decoded2 = Base64.getMimeDecoder().decode(raw);
Czy można dekodować Base64 w Javie bez java.util.Base64?
Tak, ale na Java 8+ nie ma ku temu powodu. Przed Java 8 programiści używali sun.misc.BASE64Decoder (wewnętrzna klasa, usunięta w Java 9+), javax.xml.bind.DatatypeConverter.parseBase64Binary() (usunięta w Java 11) lub Apache Commons Codec. Wszystkie trzy są przestarzałe lub wymagają dodatkowej zależności. Korzystaj z java.util.Base64 — jest szybsza, jest częścią JDK i obsługuje wszystkie trzy warianty (basic, URL-safe, MIME).
Powiązane narzędzia
- Koder Base64 — zakoduj tekst lub dane binarne do Base64 w przeglądarce; przydatne do generowania danych testowych do wklejenia w testach jednostkowych Java.
- Dekoder JWT — podziel i zdekoduj wszystkie trzy segmenty JWT naraz, z inspekcją payloadu pole po polu — szybsze niż pisanie klasy Java, gdy chcesz tylko odczytać token.
- Dekoder URL — dekoduj ciągi zakodowane procentowo, przydatne gdy odpowiedzi API łączą dane Base64url z parametrami zapytania zakodowanymi procentowo.
- Formater JSON — po zdekodowaniu payloadu JWT zakodowanego Base64 lub konfiguracji API, wklej tutaj JSON, aby go sformatować i zwalidować strukturę.