Das Crate einbinden und einen String kodieren
[dependencies]
base64 = "0.22" # the snippets below also build with 0.23
Seit 0.21 läuft alles über eine Engine. Das Modul prelude exportiert den Trait Engine und vier fertige Engines:
use base64::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let enc = BASE64_STANDARD.encode("héllo wörld");
println!("{enc}"); // aMOpbGxvIHfDtnJsZA==
let bytes = BASE64_STANDARD.decode(&enc)?;
println!("{}", String::from_utf8(bytes)?); // héllo wörld
Ok(())
}
encode akzeptiert alles, was AsRef<[u8]> ist, also funktionieren &str, String, Vec<u8> und Byte-Literale. Rust-Strings sind UTF-8, ein Umwandlungsschritt entfällt also. String::from_utf8 liefert einen Fehler, statt zu raten, wenn die dekodierten Bytes kein gültiges UTF-8 sind.
Die Namen aus dem Prelude entsprechen base64::engine::general_purpose:
| Prelude | Engine | Alphabet | Padding beim Kodieren | Padding beim Dekodieren |
|---|---|---|---|---|
BASE64_STANDARD | STANDARD | + / | ja | erforderlich |
BASE64_STANDARD_NO_PAD | STANDARD_NO_PAD | + / | nein | muss fehlen |
BASE64_URL_SAFE | URL_SAFE | - _ | ja | erforderlich |
BASE64_URL_SAFE_NO_PAD | URL_SAFE_NO_PAD | - _ | nein | muss fehlen |
URL-sicheres Base64 mit und ohne Padding
let d = b"<<???>>";
BASE64_URL_SAFE.encode(d); // "PDw_Pz8-Pg=="
BASE64_URL_SAFE_NO_PAD.encode(d); // "PDw_Pz8-Pg"
let back = BASE64_URL_SAFE_NO_PAD.decode("PDw_Pz8-Pg")?; // b"<<???>>"
Die No-Pad-Engines lehnen Eingaben mit Padding ab (BASE64_URL_SAFE_NO_PAD.decode("PDw_Pz8-Pg==") liefert Err(InvalidPadding)). Nehmen Sie Tokens von mehreren Erzeugern an, bauen Sie eine Engine, der das egal ist:
use base64::alphabet;
use base64::engine::general_purpose::{GeneralPurpose, GeneralPurposeConfig};
use base64::engine::DecodePaddingMode;
const URL_LENIENT: GeneralPurpose = GeneralPurpose::new(
&alphabet::URL_SAFE,
GeneralPurposeConfig::new()
.with_encode_padding(false)
.with_decode_padding_mode(DecodePaddingMode::Indifferent),
);
URL_LENIENT.decode("PDw_Pz8-Pg").is_ok(); // true
URL_LENIENT.decode("PDw_Pz8-Pg==").is_ok(); // true
Die anderen Modi sind RequireCanonical (Standard bei Engines mit Padding) und RequireNone. Hintergrund zu den Varianten: Base64 vs. Base64URL und Padding erklärt.
Eine Datei kodieren und dekodieren
let data = std::fs::read("hello.txt")?;
println!("{}", BASE64_STANDARD.encode(&data)); // aGVsbG8K
std::fs::write("copy.txt", BASE64_STANDARD.decode("aGVsbG8K")?)?;
Um ohne neue Allokation an einen vorhandenen Puffer anzuhängen, verwenden Sie encode_string:
let mut s = String::from("Basic ");
BASE64_STANDARD.encode_string(b"user:pass", &mut s);
println!("{s}"); // Basic dXNlcjpwYXNz
Streaming mit EncoderWriter und DecoderReader
Die Module write und read umhüllen std::io-Typen, große Dateien liegen also nie komplett im Speicher:
use std::fs::File;
use std::io::{self, Read};
let mut input = File::open("big.bin")?;
let mut w = base64::write::EncoderWriter::new(File::create("big.b64")?, &BASE64_STANDARD);
io::copy(&mut input, &mut w)?;
w.finish()?; // writes the final block and padding
let mut r = base64::read::DecoderReader::new(File::open("big.b64")?, &BASE64_STANDARD);
let mut out = Vec::new();
r.read_to_end(&mut out)?;
Rufen Sie finish() ausdrücklich auf. Auch beim Drop versucht der Writer zu flushen, kann dabei aber keine Fehler melden. Bei einer 300-KB-Testdatei entsprach die gestreamte Ausgabe BASE64_STANDARD.encode, und die dekodierten Bytes stimmten mit dem Original überein.
Validierung und DecodeError
decode liefert Result<Vec<u8>, DecodeError>. Das sind die Ergebnisse mit BASE64_STANDARD, gezeigt als Debug-Ausgabe von 0.22.1 und als Display-Meldung:
| Eingabe | Variante | Meldung |
|---|---|---|
PDw_Pz8-Pg== | InvalidByte(3, 95) | Invalid symbol 95, offset 3. |
aGk | InvalidPadding | Invalid padding |
aGk=!! | InvalidByte(3, 61) | Invalid symbol 61, offset 3. |
a | InvalidLength(1) | Invalid input length: 1 |
aGl= | InvalidLastSymbol(2, 108) | Invalid last symbol 108, offset 2. |
"aGVs\nbG8K" | InvalidByte(4, 10) | Invalid symbol 10, offset 4. |
Bytewerte sind dezimal: 95 ist _, 61 ist =, 10 ist ein Zeilenumbruch. InvalidLastSymbol bedeutet Padding-Bits ungleich null, die dieses Crate standardmäßig ablehnt; with_decode_allow_trailing_bits(true) lockert das. In 0.23 hat sich die Variante InvalidLastSymbol geändert, ihre Meldung lautet jetzt Invalid last symbol 0x6c ('l') at offset 2, decoded as 0b00100101. Matchen Sie auf den Variantennamen, nicht auf den Text.
use base64::DecodeError;
match BASE64_STANDARD.decode(input) {
Ok(bytes) => { /* use bytes */ }
Err(DecodeError::InvalidByte(offset, byte)) => eprintln!("bad byte {byte} at {offset}"),
Err(e) => eprintln!("invalid Base64: {e}"),
}
Fügen Sie einen fehlerhaften String in den Base64-Validator ein, um das schuldige Zeichen zu sehen; die Anleitung zu Base64-Fehlern geht die Ursachen durch.
Fallstricke
- Alte Tutorials.
encode_config(x, base64::URL_SAFE)und die Config-Konstanten stammen aus der Zeit vor 0.21 und kompilieren nicht mehr;base64::encode(x)baut noch, mit einer Deprecation-Warnung. Übersetzen Sie sie inURL_SAFE.encode(x)undSTANDARD.encode(x). - Trait-Import vergessen. Ohne
use base64::Engine;(oder das Prelude) scheitert der Aufruf von.encodeauf einer Engine mit „no method namedencodefound“. - Leerraum. Der Decoder behandelt Zeilenumbrüche und Leerzeichen als ungültige Bytes. Entfernen Sie sie, zum Beispiel mit
s.split_ascii_whitespace().collect::<String>(). - Keine MIME-Hilfe. Das Crate bricht keine Zeilen um. Teilen Sie die Ausgabe selbst in Abschnitte zu 76 Zeichen, wenn Sie E-Mail-Inhalte erzeugen.
Versionshinweise
- 0.21: Engine-API eingeführt; freie Funktionen
encode/decodeals veraltet markiert,*_config-Funktionen entfernt. Konfigurationen sindGeneralPurposeConfigplusDecodePaddingMode. - 0.22:
DecodeError::InvalidLengthbezieht sich jetzt auf die Anzahl gültiger Symbole;decode_slicefunktioniert mit exakt bemessenen Puffern. - 0.23: SIMD-Engines hinter dem Standard-Feature
simd-unsafe, mehr vorkonfigurierte Konstanten, eigene Padding-Symbole, MSRV 1.71. Die auf dieser Seite verwendeten General-Purpose-Engines sind unverändert.
Häufige Fragen
Warum ist base64::encode als veraltet markiert?
Seit 0.21 sind die freien Funktionen base64::encode und base64::decode veraltete Wrapper (in 0.23 noch vorhanden). Verwenden Sie stattdessen eine Engine: use base64::prelude::*; und dann BASE64_STANDARD.encode(data).
Warum lehnt das Crate base64 Eingaben ohne Padding ab?
STANDARD verlangt kanonisches Padding. Verwenden Sie URL_SAFE_NO_PAD oder STANDARD_NO_PAD für Eingaben ohne Padding, oder bauen Sie eine Engine mit DecodePaddingMode::Indifferent, die beides akzeptiert.
Überspringt das Crate base64 Zeilenumbrüche?
Nein. "aGVs\nbG8K" scheitert mit InvalidByte(4, 10). Entfernen Sie Leerraum, bevor Sie MIME- oder PEM-Inhalte dekodieren.