¿Cómo convierto un vector de bytes (u8) en una cadena?

94

Estoy tratando de escribir un cliente TCP / IP simple en Rust y necesito imprimir el búfer que obtuve del servidor.

¿Cómo convierto a Vec<u8>(o a &[u8]) a a String?

Athabaska Dick
fuente

Respuestas:

98

Para convertir un segmento de bytes en un segmento de cadena (asumiendo una codificación UTF-8):

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);
}

La conversión está en su lugar y no requiere una asignación. Puede crear un a Stringpartir del segmento de cadena si es necesario llamando .to_owned()al segmento de cadena (hay otras opciones disponibles ).

La referencia de la biblioteca para la función de conversión:

Gavinb
fuente
Es posible que desee agregar que esto es posible porque Vec coacciona a las rebanadas
torkleyy
aunque el código de ejemplo no usa un Vector :-)
Andrew Mackenzie
Aunque es cierto que from_utf8no se asigna, vale la pena mencionar que necesita escanear los datos para validar la corrección de utf-8. Entonces, esta no es una operación O (1) (que uno puede pensar al principio)
Zargony
64

Yo prefiero String::from_utf8_lossy:

fn main() {
    let buf = &[0x41u8, 0x41u8, 0x42u8];
    let s = String::from_utf8_lossy(buf);
    println!("result: {}", s);
}

Convierte bytes UTF-8 no válidos en , por lo que no se requiere manejo de errores. Es bueno para cuando no lo necesitas y yo apenas lo necesito. De hecho, obtienes un beneficio Stringde esto. Debería facilitar un poco la impresión de lo que obtiene del servidor.

A veces, es posible que deba usar el into_owned()método, ya que se clona al escribir.

Bjorn
fuente
3
¡Muchas gracias por la into_owned()sugerencia! Era exactamente lo que estaba buscando (esto hace que se convierta en un valor adecuado Stringque puede devolver como valor de retorno de un método, por ejemplo).
Per Lundberg
48

Si realmente tiene un vector de bytes ( Vec<u8>) y desea convertirlo a String, lo más eficiente es reutilizar la asignación con String::from_utf8:

fn main() {
    let bytes = vec![0x41, 0x42, 0x43];
    let s = String::from_utf8(bytes).expect("Found invalid UTF-8");
    println!("{}", s);
}
Pastor
fuente
2
¡Gracias! ¿Por qué las otras dos respuestas ignoraron la pregunta?
Jehan
1
@Jehan porque la gente generalmente no es buena para hacer preguntas, especialmente cuando son nuevos en un idioma. Rust hace una distinción entre una matriz , una porción y una Vec, pero los recién llegados no conocen las diferencias. Sin embargo, asegúrese de votar a favor de todas las preguntas y respuestas que resulten útiles.
Shepmaster
Tenga en cuenta que, como lo menciona @Bjorn Tipling, puede usar String::from_utf8_lossyen su lugar aquí, entonces no necesita la llamada esperada .
James Ray
2
Editar: tenga en cuenta que, como lo menciona @Bjorn Tipling, puede pensar que puede usarlo String::from_utf8_lossyaquí, entonces no necesita la expectllamada, pero la entrada es una porción de bytes (&'a [u8] ). OTOH, también hay from_utf8_unchecked. "Si está seguro de que el trozo byte es UTF-8 válidos, y no quiere incurrir en los gastos generales de la conversión, hay una versión insegura de esta función [ from_utf8_lossy], from_utf8_uncheckedque tiene el mismo comportamiento, pero se salta los controles. "
James Ray
Tenga en cuenta que puede utilizar &vec_of_bytespara convertir de nuevo en un segmento de bytes, como se indica en los ejemplos de from_utf8_lossy. doc.rust-lang.org/std/string/…
James Ray