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?

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:


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.


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

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.