Athabaska Dick
Athabaska Dick

Reputation: 4281

How do I convert a Vector of bytes (u8) to a string?

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

Answers (6)

stach
stach

Reputation: 2171

v.iter().map(|&c| char::from(c)).collect()

Upvotes: -3

Mahmoud Al-Qudsi
Mahmoud Al-Qudsi

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

gavinb
gavinb

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

PPP
PPP

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

Bjorn
Bjorn

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

Shepmaster
Shepmaster

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

Related Questions