str::from_utf8¶
Level: reference · for working programmers
One line: Validates a &[u8] and returns Result<&str, Utf8Error> — the checked way in, borrowing rather than copying.
Stable since 1.87.0. Usable in a const context.
An associated function, so it is str::from_utf8(bytes). It scans the bytes once and either hands back a &str over the same memory or reports where the scan failed.
Utf8Error is unusually informative: valid_up_to() gives the number of bytes that were fine, and error_len() distinguishes an invalid sequence (Some(n)) from an input that simply stops mid-character (None). That second case is what you get reading a stream in fixed-size chunks, and it is a signal to wait for more bytes rather than to reject the input.
For lossy decoding — replace bad sequences with U+FFFD and carry on — use String::from_utf8_lossy.
const fn, so a byte literal can be validated at compile time.
Example¶
str_from_utf8.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
// The invalid byte arrays below are the point of the example, so the
// lint that spots them is turned off rather than worked around.
#![allow(invalid_from_utf8)]
fn main() {
let good = [104, 105];
println!("{:?}", str::from_utf8(&good));
// Invalid sequence: where it failed, and how long the bad run is.
let bad = [104, 0xff, 105];
match str::from_utf8(&bad) {
Ok(s) => println!("{s:?}"),
Err(e) => println!("valid_up_to {} error_len {:?}", e.valid_up_to(), e.error_len()),
}
// Truncated input: error_len is None, meaning "incomplete", not "invalid".
let cut = "é".as_bytes();
println!("{:?}", str::from_utf8(&cut[..1]).unwrap_err().error_len());
// Borrowed, not copied: the same bytes, reinterpreted.
let owned = vec![104, 105];
let view = str::from_utf8(&owned).unwrap();
println!("{view:?} from a {}-byte buffer", owned.len());
// const validation.
const BYTES: &[u8] = b"compiled";
const TEXT: &str = match str::from_utf8(BYTES) { Ok(s) => s, Err(_) => "" };
println!("{TEXT:?}");
}
Verified output of str_from_utf8.rs — regenerated by tools/run_examples.py, never hand-typed.
See also¶
str::from_utf8_mut— the mutable versionstr::from_utf8_unchecked— skipping the scan, unsafelyString::from_utf8— the owning version, which takes aVec<u8>String::from_utf8_lossy— replacing bad bytes instead of failing
str::from_utf8 in the standard library ↗
Po polsku¶
str::from_utf8 sprawdza tablicę bajtów i zwraca Result<&str, Utf8Error> — bez kopiowania, bo w razie powodzenia dostajesz wycinek łańcucha (string slice) nad tymi samymi bajtami, tylko zinterpretowanymi jako tekst. Dla polskiego tekstu najciekawsze jest to, co niesie Utf8Error: każda litera z ogonkiem lub kreską zajmuje w UTF-8 dwa bajty, więc czytając strumień porcjami o stałym rozmiarze prędzej czy później przetniesz „ż” na pół — i wtedy error_len() zwraca None, co znaczy „dane się urwały, dosyłaj resztę”, a nie „dane są zepsute” (to jest Some(n), plus valid_up_to() mówiące, ile bajtów było dobrych). Pomylenie tych dwóch przypadków to klasyczny sposób na odrzucenie całkiem poprawnego wejścia; jeśli zamiast błędu wolisz podstawić znak zastępczy U+FFFD i liczyć dalej, to już zadanie dla String::from_utf8_lossy.
Szukaj po polsku: kodowanie UTF-8 · polskie znaki diakrytyczne w UTF-8 · walidacja bajtów · rust str::from_utf8 Utf8Error · rust error_len valid_up_to