Reputation: 4281
I am trying to write simple TCP/IP client in Rust and I need to print out the buffer I got from the server.
How do I convert a Vec<u8>
(or a &[u8]
) to a String
?
Upvotes: 294
Views: 316673
Reputation: 29579
To optimally convert a Vec<u8>
possibly containing non-UTF-8 characters/byte sequences into a UTF-8 String
without any unneeded allocations, you'll want to optimistically try calling String::from_utf8()
then resort to String::from_utf8_lossy()
.
let buffer: Vec<u8> = ...;
let utf8_string = String::from_utf8(buffer)
.map_err(|non_utf8| String::from_utf8_lossy(non_utf8.as_bytes()).into_owned())
.unwrap();
The approach suggested in the other answers will result in two owned buffers in memory even in the happy case (with valid UTF-8 data in the vector): one with the original u8
bytes and the other in the form of a String
owning its characters. This approach will instead attempt to consume the Vec<u8>
and marshal it as a Unicode String
directly and only failing that will it allocate room for a new string containing the lossily UTF-8 decoded output.
Upvotes: 5
Reputation: 20048
To convert a slice of bytes to a string slice (assuming a UTF-8 encoding):
use std::str;
//
// pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error>
//
// Assuming buf: &[u8]
//
fn main() {
let buf = &[0x41u8, 0x41u8, 0x42u8];
let s = match str::from_utf8(buf) {
Ok(v) => v,
Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
};
println!("result: {}", s);
}
The conversion is in-place, and does not require an allocation. You can create a String
from the string slice if necessary by calling .to_owned()
on the string slice (other options are available).
If you are sure that the byte slice is valid UTF-8, and you don’t want to incur the overhead of the validity check, there is an unsafe version of this function, from_utf8_unchecked
, which has the same behavior but skips the check.
If you need a String instead of a &str, you may also consider String::from_utf8
instead.
The library references for the conversion function:
Upvotes: 310
Reputation: 1870
In my case I just needed to turn the numbers into a string, not the numbers to letters according to some encoding, so I did
fn main() {
let bytes = vec![0x41, 0x42, 0x43];
let s = format!("{:?}", &bytes);
println!("{}", s);
}
Upvotes: 11
Reputation: 71950
I prefer String::from_utf8_lossy
:
fn main() {
let buf = &[0x41u8, 0x41u8, 0x42u8];
let s = String::from_utf8_lossy(buf);
println!("result: {}", s);
}
It turns invalid UTF-8 bytes into � and so no error handling is required. It's good for when you don't need that and I hardly need it. You actually get a String
from this. It should make printing out what you're getting from the server a little easier.
Sometimes you may need to use the into_owned()
method since it's clone on write.
Upvotes: 180
Reputation: 431939
If you actually have a vector of bytes (Vec<u8>
) and want to convert to a String
, the most efficient is to reuse the allocation with String::from_utf8
:
fn main() {
let bytes = vec![0x41, 0x42, 0x43];
let s = String::from_utf8(bytes).expect("Found invalid UTF-8");
println!("{}", s);
}
Upvotes: 102