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.