Codifica Base64 in Java — Esempi java.util.Base64

·Java Security & API Engineer·Revisionato daPavel Novak·Pubblicato

Usa il Codificatore Base64 Online gratuito direttamente nel tuo browser — nessuna installazione.

Prova Codificatore Base64 Online online →

Ogni volta che configuro un header HTTP Basic Auth, incorporo un certificato in un secret Kubernetes o trasmetto dati binari attraverso un'API JSON, il primo passo è sempre lo stesso: codificare in Base64 i byte grezzi in una stringa sicura per ASCII. Java semplifica tutto questo con java.util.Base64, l'API standard disponibile da Java 8 che ha sostituito il deprecato sun.misc.BASE64Encoder. Per una codifica rapida al volo senza scrivere codice, il Base64 Encoder di ToolDeck la gestisce istantaneamente nel browser. Questa guida copre Base64.getEncoder(), getUrlEncoder(), getMimeEncoder(), la codifica di file, lo streaming con wrap(OutputStream), e gli errori che mettono in difficoltà anche gli sviluppatori Java esperti. Tutti gli esempi compilano su Java 8 fino a Java 21+.

  • Base64.getEncoder().encodeToString(bytes) è il one-liner standard — integrato nel JDK da Java 8, invariato in Java 17 e 21.
  • Passa sempre StandardCharsets.UTF_8 a String.getBytes() prima della codifica — ometterlo usa il default della piattaforma, che varia tra le JVM.
  • getUrlEncoder() produce output URL-safe (- al posto di +, _ al posto di /) e withoutPadding() rimuove i caratteri = finali.
  • getMimeEncoder() inserisce interruzioni di riga ogni 76 caratteri — richiesto dai formati email (MIME) e dai certificati PEM.
  • Per file di grandi dimensioni, usa Base64.getEncoder().wrap(OutputStream) per lo streaming senza caricare l'intero file in memoria.

Cos'è la codifica Base64?

Base64 converte dati binari arbitrari in una stringa composta da 64 caratteri ASCII stampabili: A-Z, a-z, 0-9, + e /. Ogni 3 byte di input producono esattamente 4 caratteri Base64. Se la lunghezza dell'input non è un multiplo di 3, vengono aggiunti uno o due caratteri di padding =. L'output codificato è sempre circa il 33% più grande dei dati originali.

Base64 non è cifratura. Chiunque abbia la stringa codificata può decodificarla. Il suo scopo è la sicurezza del trasporto: gli header HTTP, i payload JSON, i documenti XML e il corpo delle email sono protocolli basati su testo che non possono trasportare byte binari grezzi senza corruzione. I casi d'uso comuni in Java includono l'autenticazione HTTP Basic, l'incorporamento di certificati PEM, la memorizzazione di dati binari in colonne di testo dei database e la costruzione di segmenti di token JWT.

Before · text
After · text
deploy-svc:sk_live_4eC39HqLyjWDarjtT1zdp7dc
ZGVwbG95LXN2Yzpza19saXZlXzRlQzM5SHFMeWpXRGFyanRUMXpkcDdkYw==

Base64.getEncoder().encodeToString() — L'API standard

java.util.Base64 è stata introdotta in Java 8 come sostituto ufficiale di sun.misc.BASE64Encoder. La classe fornisce tre factory method statici — ognuno restituisce un'istanza della classe Base64.Encoder annidata — che coprono le tre varianti Base64 definite nell'RFC 4648. Non occorre nessuna libreria di terze parti. Nessuna dipendenza Maven. Basta importare e chiamare.

Esempio minimale — Codifica una String

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

public class EncodeDemo {
    public static void main(String[] args) {
        String credentials = "monitoring-svc:9f2a7c4e-b1d8-4a3f";
        byte[] credentialBytes = credentials.getBytes(StandardCharsets.UTF_8);

        String encoded = Base64.getEncoder().encodeToString(credentialBytes);
        System.out.println(encoded);
        // bW9uaXRvcmluZy1zdmM6OWYyYTdjNGUtYjFkOC00YTNm
    }
}

Il passaggio chiave che molti sviluppatori Java mancano al primo tentativo: una String deve essere convertita in byte[] prima della codifica. Base64 opera sui byte, non sui caratteri. encodeToString() accetta un byte[] e restituisce direttamente la String Base64. Se hai bisogno del risultato codificato come byte invece, usa encode(byte[]) — restituisce un byte[] dei caratteri Base64 codificati in ASCII, utile quando scrivi direttamente su un OutputStream o costruisci frame di protocollo binario.

HTTP Basic Auth — Il caso d'uso più comune

L'autenticazione HTTP Basic è probabilmente il motivo più comune per cui gli sviluppatori Java ricorrono alla codifica Base64. La specifica (RFC 7617) richiede che la stringa di credenziali username:password sia codificata in Base64 e inserita nell'header Authorization. Ho visto questo fatto in modo errato più volte di quanto possa contare — di solito dimenticando il separatore due punti o codificando i componenti separatamente.

Java — Header HTTP Basic Auth
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class BasicAuthExample {
    public static void main(String[] args) throws Exception {
        String username = "metrics-exporter";
        String apiKey = "sk_live_4eC39HqLyjWDarjtT1zdp7dc";

        // username:password → Base64
        String credentials = username + ":" + apiKey;
        String authHeader = "Basic " + Base64.getEncoder()
            .encodeToString(credentials.getBytes(StandardCharsets.UTF_8));

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.example.com/v2/metrics"))
            .header("Authorization", authHeader)
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println(response.statusCode());  // 200
    }
}

Round-Trip — Codifica e decodifica

Java 8+ — round-trip encode e decode
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class RoundTrip {
    public static void main(String[] args) {
        String original = "X-Correlation-ID: req_8a4f2c91-e7b3-4d56-9012-3f7a8b9c0d1e";

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

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

        System.out.println(original.equals(decoded));  // true
    }
}
Nota:L'API java.util.Base64 è identica da Java 8 a Java 17 e Java 21. Non è necessaria alcuna migrazione quando si aggiorna il JDK. Lo stesso codice compila ed esegue su qualsiasi versione da Java 8 in poi.

Codifica di dati non String — byte[], UUID e Timestamp

La codifica Base64 in Java inizia sempre con un byte[]. Le stringhe si convertono tramite getBytes(StandardCharsets.UTF_8), ma gli altri tipi richiedono prima un passaggio di conversione. UUID, timestamp e identificatori numerici devono essere serializzati in una stringa o in una rappresentazione byte prima di poterli codificare in Base64.

UUID — Codifica come rappresentazione String

Java — Codifica Base64 di un UUID
import java.util.Base64;
import java.util.UUID;
import java.nio.charset.StandardCharsets;

UUID sessionId = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
String encoded = Base64.getEncoder()
    .encodeToString(sessionId.toString().getBytes(StandardCharsets.UTF_8));
System.out.println(encoded);
// NmJhN2I4MTAtOWRhZC0xMWQxLTgwYjQtMDBjMDRmZDQzMGM4

UUID compatto — Codifica i 16 byte grezzi

Se vuoi un risultato codificato più breve, estrai i 128 bit dell'UUID come 16 byte grezzi invece di convertirli nella forma stringa a 36 caratteri. L'output Base64 scende da 48 caratteri a 24.

Java — codifica UUID compatta
import java.nio.ByteBuffer;
import java.util.Base64;
import java.util.UUID;

UUID eventId = UUID.fromString("550e8400-e29b-41d4-a716-446655440000");

ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
buffer.putLong(eventId.getMostSignificantBits());
buffer.putLong(eventId.getLeastSignificantBits());

String compact = Base64.getUrlEncoder()
    .withoutPadding()
    .encodeToString(buffer.array());
System.out.println(compact);
// VQ6EAOKbQdSnFkRmVUQAAA
// 22 caratteri contro 48 dell'approccio basato su stringa

Timestamp e payload misto

Java — codifica di un payload JSON con timestamp
import java.time.Instant;
import java.util.Base64;
import java.nio.charset.StandardCharsets;

// Simulazione di un payload in stile JWT
String payload = String.format(
    "{"sub":"usr_7b3c","iss":"auth.internal","iat":%d,"exp":%d}",
    Instant.now().getEpochSecond(),
    Instant.now().plusSeconds(3600).getEpochSecond()
);

String encoded = Base64.getUrlEncoder()
    .withoutPadding()
    .encodeToString(payload.getBytes(StandardCharsets.UTF_8));
System.out.println(encoded);
// eyJzdWIiOiJ1c3JfN2IzYyIsImlzcyI6ImF1dGguaW50ZXJuYWwiLCJpYXQiOj... (URL-safe, senza padding)
Attenzione:Non chiamare toString() su un byte[] aspettandoti il suo contenuto — otterrai l'hash dell'identità dell'array come [B@6d06d69c. Usa new String(bytes, StandardCharsets.UTF_8) o passa l'array di byte direttamente a encodeToString().

Riferimento ai metodi di Base64.Encoder

La classe java.util.Base64 espone tre factory method, ognuno restituisce un Base64.Encoder configurato per una variante specifica. Le istanze dell'encoder sono thread-safe e stateless — creale una volta e riutilizzale.

Metodo
Tipo
Descrizione
getEncoder()
Base64.Encoder
Restituisce un encoder base RFC 4648 con alfabeto standard (A-Z, a-z, 0-9, +, /)
getUrlEncoder()
Base64.Encoder
Restituisce un encoder con alfabeto URL-safe (- al posto di +, _ al posto di /)
getMimeEncoder()
Base64.Encoder
Restituisce un encoder MIME che inserisce interruzioni di riga \r\n ogni 76 caratteri
getMimeEncoder(lineLength, lineSeparator)
Base64.Encoder
Encoder MIME con lunghezza di riga e separatore personalizzati
encoder.withoutPadding()
Base64.Encoder
Restituisce un encoder che omette i caratteri di padding = finali
encoder.encode(byte[])
byte[]
Codifica un array di byte e restituisce un array di byte codificati
encoder.encodeToString(byte[])
String
Codifica un array di byte e restituisce direttamente una String codificata
encoder.wrap(OutputStream)
OutputStream
Avvolge un OutputStream per la codifica Base64 in streaming

Base64.getUrlEncoder() — Codifica URL-Safe

L'encoder URL-safe usa un alfabeto alternativo dove + diventa - e / diventa _, come definito nella Sezione 5 dell'RFC 4648. Questo è importante ogni volta che la stringa Base64 compare in un parametro di query URL, un nome di file o un valore di cookie — i caratteri Base64 standard entrano in conflitto con i delimitatori URL e i caratteri riservati del filesystem.

Java — Codifica Base64 URL-safe
import java.util.Base64;
import java.nio.charset.StandardCharsets;

String redirectUri = "https://app.internal/callback?state=auth_pending&nonce=9f2a7c";
byte[] data = redirectUri.getBytes(StandardCharsets.UTF_8);

// Encoder standard — contiene + e / che rompono gli URL
String standard = Base64.getEncoder().encodeToString(data);
System.out.println(standard);
// aHR0cHM6Ly9hcHAuaW50ZXJuYWwvY2FsbGJhY2s/c3RhdGU9YXV0aF9wZW5kaW5nJm5vbmNlPTlmMmE3Yw==

// Encoder URL-safe — sicuro per parametri di query e nomi di file
String urlSafe = Base64.getUrlEncoder().encodeToString(data);
System.out.println(urlSafe);
// aHR0cHM6Ly9hcHAuaW50ZXJuYWwvY2FsbGJhY2s_c3RhdGU9YXV0aF9wZW5kaW5nJm5vbmNlPTlmMmE3Yw==

// URL-safe senza padding — per JWT e token compatti
String noPadding = Base64.getUrlEncoder().withoutPadding().encodeToString(data);
System.out.println(noPadding);
// aHR0cHM6Ly9hcHAuaW50ZXJuYWwvY2FsbGJhY2s_c3RhdGU9YXV0aF9wZW5kaW5nJm5vbmNlPTlmMmE3Yw

La variante withoutPadding() rimuove i caratteri = finali. Le specifiche JWT richiedono Base64 URL-safe senza padding per i segmenti header e payload, quindi getUrlEncoder().withoutPadding() è esattamente la chiamata che ti serve quando costruisci o manipoli token JWT manualmente.

Nota:Il metodo withoutPadding() restituisce una nuova istanza encoder — non modifica l'originale. Entrambe possono essere assegnate a campi static final e riutilizzate in sicurezza tra i thread.

Codifica da file e risposta API

I due scenari reali più comuni per la codifica Base64 in Java: leggere un file binario dal disco (certificati, immagini, bundle di configurazione) e codificare dati ricevuti da una risposta HTTP.

Codifica un file in Base64

Java — codifica di un file
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;

public class FileEncoder {
    public static void main(String[] args) {
        try {
            byte[] fileBytes = Files.readAllBytes(Path.of("certs/server.pem"));
            String encoded = Base64.getEncoder().encodeToString(fileBytes);

            System.out.printf("Originale: %d byte%n", fileBytes.length);
            System.out.printf("Codificato:  %d caratteri%n", encoded.length());

            // Scrivi il contenuto codificato in un file di testo
            Files.writeString(
                Path.of("certs/server.pem.b64"),
                encoded
            );
        } catch (java.io.IOException e) {
            System.err.println("Impossibile leggere il file: " + e.getMessage());
        }
    }
}

Codifica il corpo di una risposta API

Java 11+ — codifica di una risposta HTTP
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Base64;

public class ApiEncoder {
    public static void main(String[] args) {
        try {
            HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://api.example.com/v2/reports/weekly.pdf"))
                .header("Authorization", "Bearer tok_8f2a9c3d")
                .build();

            HttpResponse<byte[]> response = client.send(
                request, HttpResponse.BodyHandlers.ofByteArray()
            );

            if (response.statusCode() == 200) {
                String encoded = Base64.getEncoder()
                    .encodeToString(response.body());
                System.out.printf("Codificati %d byte → %d caratteri%n",
                    response.body().length, encoded.length());
            } else {
                System.err.printf("HTTP %d: %s%n",
                    response.statusCode(),
                    new String(response.body()));
            }
        } catch (Exception e) {
            System.err.println("Richiesta fallita: " + e.getMessage());
        }
    }
}

Una nota rapida prima della sezione CLI: se hai solo bisogno di incollare un file o una risposta API e ottenere l'output Base64 senza scrivere codice, il Base64 Encoder online gestisce sia input di testo che binari.

Codifica Base64 da riga di comando

A volte hai solo bisogno di codificare una stringa o un file dal terminale — senza progetto Java, senza IDE, senza passaggio di build. La maggior parte dei sistemi Unix include il comando base64, e se hai un JDK installato, puoi usare jshell per un approccio nativo Java.

Bash — codifica Base64 da riga di comando
# macOS / Linux — codifica una stringa
echo -n "deploy-bot:sk_prod_9f2a7c4e" | base64
# ZGVwbG95LWJvdDpza19wcm9kXzlmMmE3YzRl

# Codifica un file
base64 < certs/server.pem > certs/server.pem.b64

# Usando jshell (JDK 9+)
echo 'System.out.println(java.util.Base64.getEncoder().encodeToString("deploy-bot:sk_prod_9f2a7c4e".getBytes()))' | jshell -

# Usando java direttamente con un one-liner
java -e 'System.out.println(java.util.Base64.getEncoder().encodeToString(args[0].getBytes()))' "my-secret"
# Nota: java -e richiede JDK 23+ (JEP 477)

L'approccio con jshell è particolarmente utile quando devi verificare che il tuo codice Java produca lo stesso output di uno strumento Unix, o quando stai eseguendo il debug di una discrepanza tra ciò che il tuo servizio invia e ciò che il ricevente si aspetta. Ho un alias shell per questo.

Nota:Su macOS, il comando base64 usa -D per decodificare. Su Linux (GNU coreutils) usa -d. Il comportamento di codifica è identico su entrambi. Il flag -w 0 su Linux disabilita il ritorno a capo nell'output, che di solito è quello che vuoi quando passi il risultato ad altri comandi.

Apache Commons Codec — Alternativa ad alte prestazioni

Per la maggior parte delle applicazioni, java.util.Base64 è sufficientemente veloce. Ma se stai elaborando milioni di operazioni di codifica in un loop stretto — come pipeline di ingestione log o message broker ad alta produttività — Apache Commons Codec vale la pena di essere testato. Esiste da prima di Java 8 e offre un'alternativa collaudata con un'API leggermente diversa.

Java — Apache Commons Codec
// Maven: org.apache.commons:commons-codec:1.17.0
import org.apache.commons.codec.binary.Base64;
import java.nio.charset.StandardCharsets;

byte[] telemetryPayload = ("{"service":"metrics-collector","
    + ""host":"prod-east-07","
    + ""cpu_pct":72.4,"
    + ""mem_mb":3891,"
    + ""timestamp":1710523200}")
    .getBytes(StandardCharsets.UTF_8);

// Codifica standard
String encoded = Base64.encodeBase64String(telemetryPayload);

// Codifica URL-safe
String urlSafe = Base64.encodeBase64URLSafeString(telemetryPayload);

// Verifica se una stringa è Base64 valida
boolean valid = Base64.isBase64(encoded);
System.out.println(valid);  // true

Apache Commons Codec fornisce anche Base64OutputStream e Base64InputStream per scenari di streaming, e include un metodo di validazione che all'encoder JDK manca. Se Commons Codec è già nel tuo albero delle dipendenze (è incluso in molti progetti Apache), non c'è motivo di non usarlo.

Guava BaseEncoding

La libreria Guava di Google include BaseEncoding, che offre un'API fluent per Base64 con separatori di riga configurabili, controllo del padding e supporto per entrambi gli alfabeti standard e URL-safe. L'API è leggibile, ma aggiungere Guava (circa 3 MB) solo per la codifica Base64 è eccessivo. Se Guava è già nel tuo progetto per le sue utilità di collezioni o caching, l'API di codifica è un bonus gradito.

Java — Guava BaseEncoding
// Maven: com.google.guava:guava:33.1.0-jre
import com.google.common.io.BaseEncoding;
import java.nio.charset.StandardCharsets;

byte[] webhookPayload = ("{"event":"deployment.completed","
    + ""repo":"payments-api","
    + ""sha":"a7f2c91e4b3d","
    + ""environment":"production"}")
    .getBytes(StandardCharsets.UTF_8);

// Base64 standard
String standard = BaseEncoding.base64().encode(webhookPayload);

// URL-safe
String urlSafe = BaseEncoding.base64Url().encode(webhookPayload);

// Senza padding
String noPad = BaseEncoding.base64Url().omitPadding().encode(webhookPayload);

// Con separatori di riga (stile PEM)
String wrapped = BaseEncoding.base64()
    .withSeparator("\n", 64)
    .encode(webhookPayload);

Base64.getMimeEncoder() — Output con a capo per MIME e PEM

L'encoder MIME inserisce interruzioni di riga \r\n ogni 76 caratteri, rispettando la specifica MIME (RFC 2045). I certificati PEM, gli allegati email S/MIME e alcune API legacy si aspettano questo formato. Gli encoder standard e URL-safe producono una singola riga ininterrotta — se passi il loro output a un sistema che si aspetta Base64 con a capo, potrebbe fallire silenziosamente o rifiutare i dati.

Java — Codifica MIME Base64
import java.util.Base64;
import java.nio.charset.StandardCharsets;

// Simulazione del corpo di un certificato PEM
byte[] certData = new byte[256];  // In pratica, leggi da un file .der
new java.security.SecureRandom().nextBytes(certData);

// Encoder MIME predefinito — 76 caratteri per riga, separatore \r\n
String mimeEncoded = Base64.getMimeEncoder().encodeToString(certData);
System.out.println(mimeEncoded);
// QYx2K3p8Xg7JmN1R+wFkLd...  (76 caratteri)
// Ht5Bv9CzAq0PnSjYl8WxUe...  (76 caratteri)
// ...

// Encoder MIME personalizzato — 64 caratteri per riga (standard PEM), separatore \n
Base64.Encoder pemEncoder = Base64.getMimeEncoder(64, new byte[]{'\n'});
String pemBody = pemEncoder.encodeToString(certData);
System.out.println("-----BEGIN CERTIFICATE-----");
System.out.println(pemBody);
System.out.println("-----END CERTIFICATE-----");
Attenzione:Non usare getMimeEncoder() per token JWT, header HTTP o parametri URL. I ritorni a capo corromperanno i dati in questi contesti. Usa getEncoder() o getUrlEncoder() invece.

Streaming di file grandi con Base64.getEncoder().wrap()

Caricare un intero file in un byte[] con Files.readAllBytes() funziona per file piccoli, ma per qualsiasi file oltre 50-100 MB rischi un OutOfMemoryError. Il JDK fornisce Base64.getEncoder().wrap(OutputStream), che restituisce un OutputStream che codifica i dati al volo mentre li scrivi. I byte codificati fluiscono verso lo stream sottostante senza bufferizzare l'intero input.

Java — codifica Base64 in streaming
import java.io.*;
import java.nio.file.*;
import java.util.Base64;

public class StreamingEncoder {
    public static void main(String[] args) throws IOException {
        Path inputPath = Path.of("backups/database-export.sql.gz");
        Path outputPath = Path.of("backups/database-export.sql.gz.b64");

        try (
            InputStream in = Files.newInputStream(inputPath);
            OutputStream fileOut = Files.newOutputStream(outputPath);
            OutputStream base64Out = Base64.getEncoder().wrap(fileOut)
        ) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            long totalBytes = 0;

            while ((bytesRead = in.read(buffer)) != -1) {
                base64Out.write(buffer, 0, bytesRead);
                totalBytes += bytesRead;
            }

            System.out.printf("Trasmessi in streaming %d byte attraverso l'encoder Base64%n", totalBytes);
        }
        // La chiusura di base64Out scrive automaticamente i byte di padding finali
    }
}

Il blocco try-with-resources gestisce il flush e la chiusura. Un dettaglio che coglie molti di sorpresa: il padding Base64 finale viene scritto solo quando il OutputStream avvolgente viene chiuso. Se dimentichi di chiuderlo (o chiudi solo lo stream esterno), gli ultimi caratteri dell'output codificato potrebbero mancare.

Streaming verso un socket di rete

Il metodo wrap() funziona con qualsiasi OutputStream — output di file, output di socket, corpo di risposta HTTP, persino ByteArrayOutputStream. Ecco un esempio che scrive dati codificati in Base64 direttamente in un buffer in memoria, utile per i test unitari o per costruire payload da inviare via HTTP:

Java — streaming verso ByteArrayOutputStream
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Base64;
import java.nio.charset.StandardCharsets;

ByteArrayOutputStream buffer = new ByteArrayOutputStream();

try (OutputStream encoder = Base64.getEncoder().wrap(buffer)) {
    // Scrivi i dati in chunk — simula la lettura da uno stream
    encoder.write("chunk-1:telemetry-data-".getBytes(StandardCharsets.UTF_8));
    encoder.write("chunk-2:more-payload-".getBytes(StandardCharsets.UTF_8));
    encoder.write("chunk-3:final-segment".getBytes(StandardCharsets.UTF_8));
}

String encoded = buffer.toString(StandardCharsets.UTF_8);
System.out.println(encoded);
// Y2h1bmstMTp0ZWxlbWV0cnktZGF0YS1jaHVuay0yOm1vcmUtcGF5bG9hZC1jaHVuay0zOmZpbmFsLXNlZ21lbnQ=

// Verifica del round-trip
byte[] decoded = Base64.getDecoder().decode(encoded);
System.out.println(new String(decoded, StandardCharsets.UTF_8));
// chunk-1:telemetry-data-chunk-2:more-payload-chunk-3:final-segment
Nota:La dimensione del buffer nell'esempio di streaming (8192 byte) non è arbitraria. Corrisponde alla dimensione del buffer predefinita usata da BufferedInputStream ed è un buon equilibrio tra utilizzo della memoria e overhead delle system call. Buffer più piccoli aumentano il numero di chiamate read/write; buffer più grandi sprecano memoria senza un miglioramento significativo della produttività.

Istanze encoder thread-safe — Memorizza e riutilizza

Il Base64.Encoder restituito dai factory method è immutabile e thread-safe. Chiamare Base64.getEncoder() ad ogni operazione di codifica crea un nuovo oggetto ogni volta. La JVM probabilmente ottimizzerà questo, ma memorizzare l'encoder in un campo static final rende l'intenzione chiara ed evita allocazioni inutili nei percorsi critici.

Java — istanze encoder riutilizzabili
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class TokenService {
    // Crea una volta, riutilizza ovunque — thread-safe
    private static final Base64.Encoder STANDARD = Base64.getEncoder();
    private static final Base64.Encoder URL_SAFE = Base64.getUrlEncoder().withoutPadding();
    private static final Base64.Encoder MIME = Base64.getMimeEncoder();

    public static String encodeForHeader(String value) {
        return STANDARD.encodeToString(value.getBytes(StandardCharsets.UTF_8));
    }

    public static String encodeForUrl(byte[] data) {
        return URL_SAFE.encodeToString(data);
    }

    public static String encodeForEmail(byte[] attachment) {
        return MIME.encodeToString(attachment);
    }
}

Questo pattern è particolarmente utile nei servizi Spring Boot dove una classe di utilità gestisce la codifica in più controller o metodi di servizio. La chiamata a withoutPadding() restituisce una nuova istanza encoder, quindi puoi memorizzare le varianti con e senza padding come campi separati. Ogni chiamata a encodeToString() o encode() è stateless — nessuna sincronizzazione necessaria, nessuno stato mutabile condiviso.

Errori comuni

Chiamare getBytes() senza specificare un charset

Problema: String.getBytes() senza argomento charset usa la codifica predefinita della piattaforma, che è windows-1252 su Windows, UTF-8 sulla maggior parte dei sistemi Linux e varia su macOS. Lo stesso codice produce output Base64 diversi su macchine diverse.

Soluzione: Passa sempre StandardCharsets.UTF_8 esplicitamente.

Before · Java
After · Java
String text = "Ключ доступа: prod-east";
byte[] bytes = text.getBytes();  // default di piattaforma — imprevedibile
String encoded = Base64.getEncoder().encodeToString(bytes);
String text = "Ключ доступа: prod-east";
byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
String encoded = Base64.getEncoder().encodeToString(bytes);
Usare l'encoder standard per i parametri URL

Problema: Base64.getEncoder() produce caratteri + e /. Quando inseriti in una query string URL, + viene interpretato come spazio e / come separatore di percorso, corrompendo silenziosamente il valore sul lato ricevente.

Soluzione: Usa Base64.getUrlEncoder() per qualsiasi valore che comparirà in un URL.

Before · Java
After · Java
// Token nel parametro di query URL — si romperà
String token = Base64.getEncoder()
    .encodeToString(sessionData);
String url = "https://auth.internal/verify?token=" + token;
// Codifica URL-safe — nessun carattere + o /
String token = Base64.getUrlEncoder()
    .withoutPadding()
    .encodeToString(sessionData);
String url = "https://auth.internal/verify?token=" + token;
Decodificare con la variante encoder sbagliata

Problema: Codificare con getUrlEncoder() e decodificare con getDecoder() (o viceversa) lancia IllegalArgumentException perché - e _ non sono validi nell'alfabeto Base64 standard, e + e / non sono validi nell'alfabeto URL-safe.

Soluzione: Decodifica sempre con il decoder corrispondente: getUrlDecoder() per URL-safe, getDecoder() per standard.

Before · Java
After · Java
String encoded = Base64.getUrlEncoder()
    .encodeToString(data);
// Dopo...
byte[] decoded = Base64.getDecoder()  // decoder SBAGLIATO
    .decode(encoded);
// IllegalArgumentException se encoded contiene - o _
String encoded = Base64.getUrlEncoder()
    .encodeToString(data);
// Dopo...
byte[] decoded = Base64.getUrlDecoder()  // decoder corrispondente
    .decode(encoded);
Non chiudere l'OutputStream di wrap()

Problema: L'encoder in streaming bufferizza fino a 2 byte di input in attesa di un gruppo completo di 3 byte. Se non chiudi l'OutputStream avvolgente, gli ultimi 1-4 caratteri Base64 (incluso il padding) non vengono mai scritti.

Soluzione: Usa try-with-resources o chiama close() esplicitamente sullo stream avvolto prima di leggere l'output.

Before · Java
After · Java
ByteArrayOutputStream baos = new ByteArrayOutputStream();
 OutputStream b64os = Base64.getEncoder().wrap(baos);
b64os.write(data);
// baos.toString() è INCOMPLETO — mancano i byte finali
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (OutputStream b64os = Base64.getEncoder().wrap(baos)) {
    b64os.write(data);
}  // close() scrive il padding finale
String encoded = baos.toString();  // completo

Metodi di codifica Base64 — Confronto

Metodo
URL-Safe
Streaming
Interruzioni di riga
Tipi custom
Richiede installazione
Base64.getEncoder()
✓ (wrap)
No (JDK 8+)
Base64.getUrlEncoder()
✓ (wrap)
No (JDK 8+)
Base64.getMimeEncoder()
✓ (wrap)
✓ (76 caratteri)
No (JDK 8+)
Apache Commons Codec
Dipendenza Maven
Guava BaseEncoding
✓ (configurabile)
Dipendenza Maven
jcmd / CLI base64
✓ (pipe)
N/A
Installazione di sistema

Per la maggior parte dei progetti: java.util.Base64 è la scelta giusta. Zero dipendenze, integrato nel JDK, thread-safe e copre tutte e tre le varianti RFC 4648. Ricorri ad Apache Commons Codec solo se è già nel tuo classpath e hai bisogno del metodo di validazione isBase64() o del Base64OutputStream in streaming. BaseEncoding di Guava è un'opzione ragionevole se il tuo progetto dipende già da Guava, ma aggiungere una dipendenza da 3 MB solo per Base64 è difficile da giustificare.

Tre scenari, tre scelte: servizio web standard che necessita di codifica per Basic Auth o JWT? Resta con il JDK. Progetto legacy che include già Commons Codec tramite Spring o Apache HTTP Client? Usalo — nessuna ragione di avere due librerie Base64 nel classpath. Progetto che usa Guava per caching e collezioni? Usa BaseEncoding per la sua API fluent pulita. Non aggiungere mai una libreria solo per la codifica Base64 — la versione JDK è più che sufficiente dal 2014.

Se hai bisogno di verificare rapidamente un risultato codificato senza eseguire il tuo codice Java, incollalo nel Base64 Encoder per confermare che l'output corrisponda a quello prodotto dal tuo codice.

Domande frequenti

Come si codifica una String in Base64 in Java?

Converti prima la stringa in byte usando getBytes(StandardCharsets.UTF_8), poi passa l'array di byte a Base64.getEncoder().encodeToString(). Specifica sempre UTF-8 esplicitamente — chiamare getBytes() senza argomento charset usa il default della piattaforma, che varia tra sistemi operativi e configurazioni JVM.

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

String payload = "grant_type=client_credentials&scope=read:metrics";
String encoded = Base64.getEncoder()
    .encodeToString(payload.getBytes(StandardCharsets.UTF_8));
// Z3JhbnRfdHlwZT1jbGllbnRfY3JlZGVudGlhbHMmc2NvcGU9cmVhZDptZXRyaWNz

Qual è la differenza tra Base64.getEncoder() e Base64.getUrlEncoder()?

Entrambi codificano in Base64, ma getUrlEncoder() usa l'alfabeto URL-safe definito nella Sezione 5 dell'RFC 4648. Sostituisce + con - e / con _ in modo che l'output possa comparire in URL e nomi di file senza percent-encoding. L'encoder standard usa + e / che entrano in conflitto con i parametri di query e i segmenti di percorso degli URL.

Java
byte[] data = "subject=usr_7b3c&role=admin".getBytes(StandardCharsets.UTF_8);

String standard = Base64.getEncoder().encodeToString(data);
// c3ViamVjdD11c3JfN2IzYyZyb2xlPWFkbWlu

String urlSafe = Base64.getUrlEncoder().encodeToString(data);
// c3ViamVjdD11c3JfN2IzYyZyb2xlPWFkbWlu
// (uguale qui, ma con + → - e / → _ quando compaiono)

java.util.Base64 è uguale in Java 8 e Java 17?

Sì. L'API java.util.Base64 non è cambiata da quando è stata introdotta in Java 8. La classe, le classi annidate Encoder e Decoder e tutti i factory method (getEncoder, getUrlEncoder, getMimeEncoder) sono identici in Java 8, 11, 17 e 21. Non sono necessarie migrazioni o modifiche al codice quando si aggiorna la versione del JDK.

Java
// Questo codice compila ed esegue identicamente da Java 8 a Java 21+
import java.util.Base64;
import java.nio.charset.StandardCharsets;

String encoded = Base64.getEncoder()
    .encodeToString("stable-api".getBytes(StandardCharsets.UTF_8));
System.out.println(encoded);  // c3RhYmxlLWFwaQ==

Come si codifica un file in Base64 in Java?

Leggi il file in un array di byte con Files.readAllBytes(Path) e passalo a Base64.getEncoder().encodeToString(). Per file di grandi dimensioni che non devono essere caricati interamente in memoria, usa Base64.getEncoder().wrap(OutputStream) per trasmettere in streaming l'output codificato.

Java
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;

byte[] fileBytes = Files.readAllBytes(Path.of("config/tls-cert.pem"));
String encoded = Base64.getEncoder().encodeToString(fileBytes);

Perché sun.misc.BASE64Encoder è stato deprecato?

sun.misc.BASE64Encoder era una classe interna del JDK che non ha mai fatto parte dell'API pubblica. Si trovava nel package sun.misc, che Oracle ha sempre sconsigliato esplicitamente di usare. Java 8 ha introdotto java.util.Base64 come sostituto ufficiale, pubblico e supportato. Da Java 9 con il sistema di moduli, l'accesso alle classi sun.misc produce avvisi o errori a seconda della configurazione del JDK.

Java
// Vecchio modo — NON usare, rimosso nei JDK moderni
// import sun.misc.BASE64Encoder;
// String encoded = new BASE64Encoder().encode(data);

// Modo corretto da Java 8
import java.util.Base64;
String encoded = Base64.getEncoder().encodeToString(data);

Come si esegue un round-trip Base64 encode e decode in Java?

Codifica con Base64.getEncoder().encodeToString(bytes) e decodifica con Base64.getDecoder().decode(encodedString). Converti l'array di byte decodificato in String usando new String(bytes, StandardCharsets.UTF_8). Il round-trip preserva i dati originali esattamente — a patto di usare lo stesso charset sia per getBytes() che per new String().

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

// Codifica
String original = "session_token=eyJhbGciOiJSUzI1NiJ9";
byte[] originalBytes = original.getBytes(StandardCharsets.UTF_8);
String encoded = Base64.getEncoder().encodeToString(originalBytes);

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

System.out.println(original.equals(decoded));  // true

Strumenti correlati

  • Base64 DecoderDecodifica stringhe Base64 nella loro forma originale testuale o binaria — l'operazione inversa della codifica.
  • URL EncoderCodifica le stringhe con percent-encoding per un uso sicuro negli URL — diverso dalla codifica Base64 URL-safe, ma spesso usato insieme.
  • JWT DecoderIspeziona i token JWT i cui segmenti header e payload sono JSON codificato in Base64url — decodificali senza librerie.
  • JSON FormatterFormatta i payload JSON prima o dopo la codifica Base64 — utile per il debug delle integrazioni API.
Disponibile anche in:JavaScriptPython
AO
Aisha OseiJava Security & API Engineer

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.

PN
Pavel NovakRevisore tecnico

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.