String::from_utf16le¶
Level: reference · for working programmers
One line: Decodes little-endian UTF-16 from a &[u8] — bytes, not u16s, so the endianness is stated rather than assumed.
Stable since 1.98.0.
When UTF-16 arrives over a wire or out of a file it is a byte stream, and two bytes make a code unit only once you know which order they are in. This is the explicit little-endian reading; from_utf16be is the other.
It fails on an odd number of bytes as well as on an unpaired surrogate — a trailing half-unit cannot be decoded.
It does not consume a byte-order mark. A file starting FF FE decodes to a leading U+FEFF zero-width no-break space that will not print but will break comparisons. Strip it explicitly.
Stable since Rust 1.98, so check your MSRV.
Example¶
string_from_utf16le.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
// "hi" little-endian: 0x68 0x00, 0x69 0x00
let le = [0x68, 0x00, 0x69, 0x00];
println!("{:?}", String::from_utf16le(&le));
// The same bytes read big-endian are different characters entirely.
println!("{:?}", String::from_utf16be(&le));
// An odd byte count cannot be decoded.
println!("{:?}", String::from_utf16le(&[0x68, 0x00, 0x69]).is_err());
// A BOM is decoded, not consumed.
let with_bom = [0xFF, 0xFE, 0x68, 0x00];
let decoded = String::from_utf16le(&with_bom).unwrap();
println!("{:?} first char {:?}", decoded, decoded.chars().next());
println!("stripped: {:?}", decoded.strip_prefix('\u{FEFF}'));
// Round trip through bytes.
let text = "héllo";
let bytes: Vec<u8> = text.encode_utf16().flat_map(u16::to_le_bytes).collect();
println!("{}", String::from_utf16le(&bytes).unwrap() == text);
}
Verified output of string_from_utf16le.rs — regenerated by tools/run_examples.py, never hand-typed.
See also¶
String::from_utf16be— the other byte orderString::from_utf16le_lossy— replacing bad sequences instead of failingString::from_utf16— when you already haveu16sstr::encode_utf16— the outbound direction
String::from_utf16le in the standard library ↗
Po polsku¶
To ta kolejność, którą w praktyce spotyka się najczęściej — Windows zapisuje UTF-16 jako little-endian, więc plik z Notatnika czy eksport „Unicode text” z Excela wchodzi do Rusta właśnie tędy. Prawdziwa pułapka nie tkwi jednak w kolejności bajtów, tylko w BOM-ie: from_utf16le go dekoduje, ale go nie zjada, więc początkowe FF FE zostaje w łańcuchu znaków jako U+FEFF — znak zerowej szerokości, którego nie widać na ekranie, a który psuje każde porównanie, starts_with i klucz w mapie. Widać go dokładnie w jednym miejscu: {:?} wypisuje "\u{feff}h", podczas gdy zwykłe {} pokaże po prostu h, więc do polowania na ten znak używaj formatowania debugowego, a usuwaj go jawnie przez strip_prefix('\u{FEFF}'). Faktycznie zgłaszane błędy są tylko dwa: nieparzysta liczba bajtów i niesparowany surogat.
Szukaj po polsku: znacznik BOM · niewidzialny znak na początku pliku · UTF-16LE w Windows · rust String::from_utf16le · rust strip BOM U+FEFF