Bagaimana cara mengonversi Vektor byte (u8) menjadi string

95

Saya mencoba untuk menulis klien TCP / IP sederhana di Rust dan saya perlu mencetak buffer yang saya dapatkan dari server.

Bagaimana cara mengubah a Vec<u8>(atau a &[u8]) menjadi a String?

Athabaska Dick
sumber

Jawaban:

99

Untuk mengonversi potongan byte menjadi potongan string (dengan asumsi pengkodean 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);
}

Konversi sudah ada, dan tidak memerlukan alokasi. Anda dapat membuat Stringdari potongan string jika perlu dengan memanggil .to_owned()potongan string ( opsi lain tersedia ).

Referensi perpustakaan untuk fungsi konversi:

gavinb.dll
sumber
Anda mungkin ingin menambahkan bahwa ini dimungkinkan karena Vec memaksa ke irisan
torkleyy
meskipun kode contoh sebenarnya tidak menggunakan Vektor :-)
Andrew Mackenzie
Meskipun benar itu from_utf8tidak mengalokasikan, mungkin perlu disebutkan bahwa itu perlu memindai data untuk memvalidasi kebenaran utf-8. Jadi ini bukan operasi O (1) (yang mungkin dipikirkan pada awalnya)
Zargony
66

Saya lebih suka String::from_utf8_lossy:

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

Ini mengubah byte UTF-8 yang tidak valid menjadi sehingga tidak diperlukan penanganan kesalahan. Itu bagus ketika Anda tidak membutuhkannya dan saya hampir tidak membutuhkannya. Anda benar-benar mendapatkan Stringdari ini. Seharusnya mencetak apa yang Anda dapatkan dari server sedikit lebih mudah.

Kadang-kadang Anda mungkin perlu menggunakan into_owned()metode ini karena itu kloning saat menulis.

Bjorn
sumber
4
Terima kasih banyak atas into_owned()sarannya! Persis seperti yang saya cari (ini membuatnya menjadi tepat Stringyang dapat Anda kembalikan sebagai nilai kembali dari suatu metode, misalnya).
Per Lundberg
48

Jika Anda benar-benar memiliki vektor byte ( Vec<u8>) dan ingin mengonversi menjadi String, yang paling efisien adalah menggunakan kembali alokasi dengan 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
sumber
2
Terima kasih! Mengapa dua jawaban lainnya mengabaikan pertanyaan itu?
Jehan
1
@Jehan karena orang pada umumnya tidak pandai mengajukan pertanyaan, terutama ketika mereka baru mengenal suatu bahasa. Rust membuat perbedaan antara array , slice, dan a Vec, tetapi pendatang baru tidak mengetahui perbedaannya. Pastikan untuk memberi suara positif pada semua pertanyaan dan jawaban yang terbukti berguna.
Shepmaster
Perhatikan bahwa seperti yang disebutkan oleh @Bjorn Tipling, Anda dapat menggunakan String::from_utf8_lossysebagai gantinya di sini, maka Anda tidak memerlukan panggilan yang diharapkan.
James Ray
2
Edit: Perhatikan bahwa seperti yang disebutkan oleh @Bjorn Tipling Anda mungkin berpikir Anda dapat menggunakan String::from_utf8_lossysebagai gantinya di sini, maka Anda tidak memerlukan expectpanggilan tersebut, tetapi masukan untuk itu adalah sepotong bytess ( &'a [u8]). OTOH, ada juga from_utf8_unchecked. "Jika Anda yakin bahwa slice byte berlaku UTF-8, dan Anda tidak ingin mendatangkan overhead konversi, ada versi tidak aman dari fungsi ini [ from_utf8_lossy], from_utf8_unchecked, yang memiliki perilaku yang sama tapi melompat pemeriksaan. "
James Ray
Perhatikan bahwa Anda dapat menggunakan &vec_of_bytesuntuk mengonversi kembali menjadi potongan byte, seperti yang tercantum dalam contoh from_utf8_lossy. doc.rust-lang.org/std/string/…
James Ray