242 votes

Comment convertir un vecteur d'octets (u8) en une chaîne de caractères ?

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

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

251voto

gavinb Points 9237

Pour convertir une tranche d'octets en une tranche de chaîne de caractères (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 se fait sur place et ne nécessite pas d'allocation. Vous pouvez créer un String de la tranche de chaîne si nécessaire en appelant .to_owned() sur la tranche de chaîne ( d'autres options sont disponibles ).

Si vous êtes sûr que la tranche d'octets est valide en UTF-8 et que vous ne voulez pas subir le surcoût de la vérification de validité, il existe une version non sécurisée de cette fonction, from_utf8_unchecked qui a le même comportement mais saute la vérification.

Si vous avez besoin d'une chaîne au lieu d'une &str, vous pouvez également envisager String::from_utf8 au lieu de cela.

Les références de la bibliothèque pour la fonction de conversion :

156voto

Bjorn Tipling Points 16243

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 non valides en octets et ne nécessite donc aucune gestion d'erreur. C'est bien pour les cas où vous n'avez pas besoin de cela, et je n'en ai guère besoin. En fait, vous obtenez un String de ceci. Cela devrait faciliter l'impression de ce que vous recevez du serveur.

Il est parfois nécessaire d'utiliser la fonction into_owned() puisqu'il s'agit d'un clone en écriture.

93voto

Shepmaster Points 1732

Si vous avez effectivement un vecteur d'octets ( Vec<u8> ) et que l'on souhaite convertir en 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);
}

10voto

Lucas Zanella Points 37

Dans mon cas, j'avais juste besoin de transformer les nombres en chaîne de caractères, et non les nombres en lettres selon un certain encodage.

fn main() {
    let bytes = vec![0x41, 0x42, 0x43];
    let s = format!("{:?}", &bytes);
    println!("{}", s);
}

1voto

Mahmoud Al-Qudsi Points 14815

Pour convertir de manière optimale un Vec<u8> contenant éventuellement des caractères/séquences d'octets non UTF-8 dans un fichier UTF-8 String sans allocations inutiles Pour être optimiste, vous pouvez essayer d'appeler String::from_utf8() puis de recourir à String::from_utf8_lossy() .

let buffer: Vec<u8> = ...;

let utf8_string = String::from_utf8(buffer)
    .map_err(|non_utf8| String::from_utf8_lossy(non_utf8.as_bytes()).into_owned())
    .unwrap();

L'approche proposée dans les autres réponses aboutira à deux possède des tampons en mémoire même dans le cas le plus heureux (avec des données UTF-8 valides dans le vecteur) : l'un avec l'original u8 et l'autre sous la forme d'un String s'approprier ses personnages. Cette approche tentera plutôt de consommer le Vec<u8> et le transformer en un code Unicode String directement et ce n'est qu'à défaut qu'il allouera de la place pour une nouvelle chaîne contenant la sortie décodée en UTF-8 avec perte.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X