Comment convertir un vecteur d'octets (u8) en chaîne

94

J'essaie d'écrire un client TCP / IP simple dans Rust et j'ai besoin d'imprimer le tampon que j'ai obtenu du serveur.

Comment convertir un Vec<u8>(ou un &[u8]) en un String?

Athabaska Dick
la source

Réponses:

98

Pour convertir une tranche d'octets en une tranche de chaîne (en supposant un encodage 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 conversion est en place et ne nécessite pas d'allocation. Vous pouvez créer un à Stringpartir de la tranche de chaîne si nécessaire en appelant .to_owned()la tranche de chaîne (d' autres options sont disponibles ).

La référence de la bibliothèque pour la fonction de conversion:

gavinb
la source
Vous voudrez peut-être ajouter que cela est possible parce que Vec contraint à des tranches
torkleyy
bien que l'exemple de code n'utilise pas réellement de vecteur :-)
Andrew Mackenzie
Bien qu'il soit vrai que from_utf8cela n'alloue pas, il peut être utile de mentionner qu'il doit analyser les données pour valider l'exactitude de l'utf-8. Ce n'est donc pas une opération O (1) (à laquelle on peut penser au début)
Zargony
64

Je préfère String::from_utf8_lossy:

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

Il transforme les octets UTF-8 invalides en et donc aucune gestion d'erreur n'est requise. C'est bon lorsque vous n'en avez pas besoin et que j'en ai à peine besoin. Vous obtenez en fait un Stringde cela. Cela devrait faciliter un peu l'impression de ce que vous obtenez du serveur.

Parfois, vous devrez peut-être utiliser la into_owned()méthode car elle est clonée en écriture.

Bjorn
la source
3
Merci beaucoup pour la into_owned()suggestion! C'était exactement ce que je cherchais (cela en fait un vrai Stringque vous pouvez retourner comme valeur de retour d'une méthode, par exemple).
Per Lundberg
48

Si vous avez réellement un vecteur d'octets ( Vec<u8>) et que vous souhaitez convertir en a String, le plus efficace est de réutiliser l'allocation avec String::from_utf8:

fn main() {
    let bytes = vec![0x41, 0x42, 0x43];
    let s = String::from_utf8(bytes).expect("Found invalid UTF-8");
    println!("{}", s);
}
Shepmaster
la source
2
Merci! Pourquoi les deux autres réponses ont-elles ignoré la question?
Jehan
1
@Jehan parce que les gens ne sont généralement pas doués pour poser des questions, surtout lorsqu'ils sont nouveaux dans une langue. Rust fait une distinction entre un tableau , une tranche et un Vec, mais les nouveaux venus ne connaissent pas les différences. Assurez-vous de voter pour toutes les questions et réponses qui s'avèrent utiles.
Shepmaster
Notez que comme mentionné par @Bjorn Tipling, vous pouvez utiliser à la String::from_utf8_lossyplace ici, alors vous n'avez pas besoin de l'appel attendu.
James Ray
2
Edit: Notez que comme mentionné par @Bjorn Tipling, vous pourriez penser que vous pouvez utiliser à la String::from_utf8_lossyplace ici, alors vous n'avez pas besoin de l' expectappel, mais l'entrée est une tranche de bytess ( &'a [u8]). OTOH, il y a aussi from_utf8_unchecked. « Si vous êtes sûr que la tranche d'octet est valide UTF-8, et vous ne voulez pas encourir les frais généraux de la conversion, il existe une version non sécuritaire de cette fonction [ from_utf8_lossy], from_utf8_uncheckedqui a le même comportement , mais ignore les contrôles. "
James Ray
Notez que vous pouvez utiliser &vec_of_bytespour reconvertir en une tranche d'octets, comme indiqué dans les exemples de from_utf8_lossy. doc.rust-lang.org/std/string/…
James Ray