Como faço para converter um vetor de bytes (u8) em uma string


94

Estou tentando escrever um cliente TCP / IP simples em Rust e preciso imprimir o buffer que obtive do servidor.

Como faço para converter um Vec<u8>(ou a &[u8]) em um String?

Respostas:


98

Para converter uma fatia de bytes em uma fatia de string (assumindo uma codificação 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);
}

A conversão está em vigor e não requer uma alocação. Você pode criar um a Stringpartir da fatia da string, se necessário, chamando .to_owned()a fatia da string ( outras opções estão disponíveis ).

A referência da biblioteca para a função de conversão:


Você pode querer acrescentar que isso é possível porque Vec força as fatias
— torkleyy

embora o código de exemplo não use realmente um vetor :-)
— Andrew Mackenzie

Embora seja verdade que from_utf8não aloca, vale a pena mencionar que é necessário verificar os dados para validar a correção do utf-8. Portanto, esta não é uma operação O (1) (o que se pode pensar a princípio)
— Zargony

64

Eu prefiro String::from_utf8_lossy:

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

Ele transforma bytes UTF-8 inválidos em e, portanto, nenhum tratamento de erro é necessário. É bom para quando você não precisa disso e eu quase não preciso. Você realmente obtém um Stringcom isso. Isso deve tornar a impressão do que você está obtendo do servidor um pouco mais fácil.

Às vezes, você pode precisar usar o into_owned()método, pois é clone na gravação.


3
Muito obrigado pela into_owned()sugestão! Era exatamente o que eu procurava (isso faz com que seja um próprio Stringque você pode retornar como valor de retorno de um método, por exemplo).
— Per Lundberg

48

Se você realmente tem um vetor de bytes ( Vec<u8>) e deseja converter para um String, o mais eficiente é reutilizar a alocação com 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
Obrigado! Por que as outras duas respostas ignoraram a pergunta?
— Jehan

1
@Jehan porque as pessoas geralmente não são boas em fazer perguntas, especialmente quando são novas no idioma. Rust faz uma distinção entre um array , um slice e a Vec, mas os novatos não conhecem as diferenças. No entanto, certifique-se de votar a favor de todas as perguntas e respostas que sejam úteis.
— Shepmaster

Observe que, conforme mencionado por @Bjorn Tipling, você pode usar String::from_utf8_lossyaqui, então não precisa da chamada expect.
— James Ray

2
Edit: Observe que, conforme mencionado por @Bjorn Tipling, você pode pensar que pode usar em String::from_utf8_lossyvez disso aqui, então você não precisa da expectchamada, mas a entrada para isso é uma fatia de bytess ( &'a [u8]). OTOH, há também from_utf8_unchecked. "Se você tem certeza que a fatia byte é válido UTF-8, e você não quer incorrer a sobrecarga da conversão, há uma versão insegura desta função [ from_utf8_lossy], from_utf8_uncheckedque tem o mesmo comportamento, mas ignora os cheques. "
— James Ray

Observe que você pode usar &vec_of_bytespara converter de volta em uma fatia de bytes, conforme listado nos exemplos de from_utf8_lossy. doc.rust-lang.org/std/string/…
— James Ray
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.