str::as_bytes¶
Level: reference · for working programmers
One line: Borrows the string's UTF-8 bytes as &[u8] — free, since that is already how the text is stored.
Stable since 1.0.0. Usable in a const context.
No conversion happens. A &str is a &[u8] plus a promise that the bytes are valid UTF-8, so as_bytes hands back the slice and drops the promise. Going the other way costs a check — see str::from_utf8.
Reach for it when the job is genuinely about bytes: writing to a socket, hashing, comparing against a byte literal, or an ASCII scan where indexing is legal because every byte is one character.
fn main() {
let s = "hello";
println!("{}", s.as_bytes()[0]); // 104 — you cannot write s[0]
println!("{:?}", &b"hello"[..]); // b"..." is the byte-string literal
}
The trap is treating the result as characters. s.as_bytes()[i] is a byte, and on any non-ASCII text a single character occupies several of them, so a loop over bytes that assumes "one byte, one character" is right on English input and wrong on the first accented name. s.as_bytes().len() is exactly len.
The bytes are borrowed, so the string has to outlive them. For an owned Vec<u8> use String::into_bytes, which is also free — it is the same allocation, relabelled.
Example¶
str_as_bytes.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
let s = "hé!";
println!("{:?}", s.as_bytes()); // [104, 195, 169, 33]
println!("{} bytes, {} chars", s.as_bytes().len(), s.chars().count());
// A byte-literal comparison, which is what as_bytes is really for.
println!("{}", "GET /".as_bytes().starts_with(b"GET"));
// An ASCII-only scan: legal because every byte here is one character,
// so a byte index and a character index are the same number.
let code = "A7";
let bytes = code.as_bytes();
println!("letter {:?}, digit {}", bytes[0] as char, bytes[1] - b'0');
// The trap: byte 1 of "hé!" is half of 'é'.
println!("byte 1 = {}, char 1 = {:?}", s.as_bytes()[1], s.chars().nth(1).unwrap());
}
Verified output of str_as_bytes.rs — regenerated by tools/run_examples.py, never hand-typed.
See also¶
str::bytes— the same bytes as an iterator rather than a slicestr::from_utf8— the checked trip backString::into_bytes— the owned version, also freeString::as_bytes— the same method on the owned type
str::as_bytes in the standard library ↗
Po polsku¶
as_bytes niczego nie konwertuje i nic nie kosztuje: &str jest &[u8] plus obietnica, że te bajty to poprawny UTF-8, a ta metoda oddaje sam wycinek i obietnicę porzuca — dlatego działa w kontekście const. Droga powrotna kosztuje już sprawdzenie, stąd osobne from_utf8. Pułapka jest ta, która przy polskim tekście wraca zawsze: wynik to bajty, a nie znaki. Widać to na przykładzie ze strony — "hé!" ma cztery bajty i trzy znaki, a as_bytes()[1] to 195, czyli pierwsza połowa é; z "żółw" wyjdzie siedem bajtów na cztery litery i żaden pojedynczy element nie jest literą.
Sięgaj po as_bytes, kiedy zadanie naprawdę dotyczy bajtów — zapis do gniazda, haszowanie, porównanie z literałem b"GET", skan po czystym ASCII — a nie kiedy chcesz „wziąć i-ty znak”; do tego są chars() i char_indices(). Bajty są pożyczone, więc łańcuch musi je przeżyć; gdy potrzebny jest własny Vec<u8>, użyj String::into_bytes, które też jest darmowe, bo to ta sama alokacja, tylko inaczej opisana.
Szukaj po polsku: bajty a znaki w UTF-8 · wycinek bajtów · rust str as_bytes · rust str is utf-8 bytes · rust from_utf8