Як перетворити вектор байтів (u8) у рядок


94

Я намагаюся написати простий клієнт TCP / IP у Rust, і мені потрібно роздрукувати буфер, який я отримав із сервера.

Як перетворити a Vec<u8>(або a &[u8]) в a String?

Відповіді:


98

Щоб перетворити фрагмент байтів у фрагмент рядка (припускаючи кодування 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);
}

Перетворення відбувається на місці та не потребує виділення. При необхідності можна створити Stringз фрагмента рядка, зателефонувавши .to_owned()на фрагмент рядка ( доступні інші варіанти ).

Посилання на бібліотеку для функції перетворення:


Ви можете додати, що це можливо, оскільки Vec примушує скибочки
torkleyy

хоча в прикладі коду насправді не використовується Вектор :-)
Ендрю Маккензі

Хоча це правда, що from_utf8не розподіляє, можливо, варто згадати, що йому потрібно просканувати дані, щоб перевірити правильність utf-8. Отже, це не операція O (1) (про яку можна подумати спочатку)
Заргоні

64

Я віддаю перевагу String::from_utf8_lossy:

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

Він перетворює недійсні байти UTF-8 в , тому не потрібно обробляти помилки. Це добре, коли вам це не потрібно, і я навряд чи потребую цього. Ви насправді отримуєте Stringвід цього. Це повинно полегшити друк того, що ви отримуєте від сервера.

Іноді вам може знадобитися використовувати into_owned()метод, оскільки він є клоном для запису.


3
Велике спасибі за into_owned()пропозицію! Було саме те, що я шукав (це робить це властивістю, Stringяку ви можете повернути як повернене значення з методу, наприклад).
Per Lundberg

48

Якщо ви насправді маєте вектор байт ( Vec<u8>) і хочете перетворити його на a String, найефективнішим є повторне використання розподілу за допомогою 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
Дякую! Чому інші дві відповіді проігнорували питання?
Джехан,

1
@Jehan, тому що люди, як правило, не вміють задавати питання, особливо коли вони не знайомі з мовою. Іржа робить різницю між масивом , фрагментом та a Vec, але новачки не знають відмінностей. Не забудьте подати всі питання та відповіді, які виявляються корисними.
Шепмайстер

Зауважте, що, як згадував @Bjorn Tipling, ви можете використовувати String::from_utf8_lossyзамість цього тут, то вам не потрібен дзвінок очікування.
Джеймс Рей

2
Редагувати: Зверніть увагу, що, як згадував @Bjorn Tipling, ви можете подумати, що можете String::from_utf8_lossyзамість цього скористатися тут, тоді вам не потрібен expectдзвінок, але вхідним сигналом для цього є фрагмент байт ( &'a [u8]). OTOH, є також from_utf8_unchecked. «Якщо ви впевнені , що зріз байт дійсний UTF-8, і ви не хочете брати на себе накладні витрати на перетворення, є небезпечна версія цієї функції [ from_utf8_lossy], from_utf8_unchecked, яка має таку ж поведінку , але пропускає перевірку. "
Джеймс Рей

Зауважте, що ви можете використовувати &vec_of_bytesдля перетворення назад у фрагмент байтів, як зазначено в прикладах from_utf8_lossy. doc.rust-lang.org/std/string/…
Джеймс Рей
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.