Come converto un vettore di byte (u8) in una stringa


94

Sto cercando di scrivere un semplice client TCP / IP in Rust e ho bisogno di stampare il buffer che ho ricevuto dal server.

Come si converte un Vec<u8>(o un &[u8]) in un String?

Risposte:


98

Per convertire una fetta di byte in una fetta di stringa (assumendo una codifica 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 conversione è sul posto e non richiede un'allocazione. Se necessario, puoi creare una sezione Stringdalla stringa chiamando .to_owned()la sezione della stringa ( sono disponibili altre opzioni ).

Il riferimento alla libreria per la funzione di conversione:


Potresti aggiungere che questo è possibile perché Vec costringe a
— tagliare

sebbene il codice di esempio non utilizzi effettivamente un vettore :-)
— Andrew Mackenzie

Sebbene sia vero che from_utf8non alloca, può valere la pena ricordare che è necessario scansionare i dati per convalidare la correttezza utf-8. Quindi questa non è un'operazione O (1) (cosa che si potrebbe pensare all'inizio)
— Zargony

64

Io preferisco String::from_utf8_lossy:

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

Trasforma i byte UTF-8 non validi in e quindi non è richiesta la gestione degli errori. Va bene quando non ne hai bisogno e io ne ho appena bisogno. In realtà ottieni un Stringda questo. Dovrebbe rendere un po 'più semplice la stampa di ciò che stai ricevendo dal server.

A volte potrebbe essere necessario utilizzare il into_owned()metodo poiché è clone in scrittura.


3
Grazie mille per il into_owned()suggerimento! Era esattamente quello che stavo cercando (questo lo fa diventare un corretto Stringche puoi restituire come valore di ritorno da un metodo, per esempio).
— Per Lundberg,

48

Se hai effettivamente un vettore di bytes ( Vec<u8>) e vuoi convertirlo in un String, il più efficiente è riutilizzare l'allocazione 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);
}

2
Grazie! Perché le altre due risposte ignoravano la domanda?
— Jehan

1
@Jehan perché le persone generalmente non sono brave a fare domande, specialmente quando sono nuove in una lingua. Rust fa una distinzione tra un array , uno slice e un Vec, ma i nuovi arrivati ​​non conoscono le differenze. Assicurati di dare un voto positivo a tutte le domande e risposte che si dimostrano utili.
— Shepmaster

Nota che come menzionato da @Bjorn Tipling puoi usare String::from_utf8_lossyinvece qui, quindi non hai bisogno della chiamata attesa.
— James Ray

2
Modifica: nota che, come menzionato da @Bjorn Tipling, potresti pensare di poterlo usare String::from_utf8_lossyinvece qui, quindi non hai bisogno della expectchiamata, ma l'input è una fetta di bytess ( &'a [u8]). OTOH, c'è anche from_utf8_unchecked. "Se si è certi che la fetta di byte è valido UTF-8, e non si vuole incorrere l'overhead della conversione, c'è una versione non sicura di questa funzione [ from_utf8_lossy], from_utf8_unchecked, che ha lo stesso comportamento, ma salta i controlli. "
— James Ray,

Si noti che è possibile utilizzare &vec_of_bytesper riconvertire in una porzione di byte, come elencato negli esempi di from_utf8_lossy. doc.rust-lang.org/std/string/…
— James Ray
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.