Làm cách nào để chuyển đổi Vectơ byte (u8) thành chuỗi


94

Tôi đang cố gắng viết ứng dụng TCP / IP đơn giản trong Rust và tôi cần in ra bộ đệm mà tôi nhận được từ máy chủ.

Làm cách nào để chuyển đổi a Vec<u8>(hoặc a &[u8]) thành a String?

Câu trả lời:


98

Để chuyển đổi một lát byte thành một lát chuỗi (giả sử mã hóa 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);
}

Chuyển đổi được thực hiện tại chỗ và không yêu cầu phân bổ. Bạn có thể tạo một Stringtừ lát chuỗi nếu cần bằng cách gọi .to_owned()trên lát chuỗi ( các tùy chọn khác có sẵn ).

Tham chiếu thư viện cho hàm chuyển đổi:


Bạn có thể muốn thêm rằng điều này có thể vì Vec cưỡng ép để lát
torkleyy

mặc dù các mã ví dụ không thực sự sử dụng một Vector :-)
Andrew Mackenzie

Mặc dù đúng là from_utf8nó không phân bổ, nhưng có thể đáng nói là nó cần quét dữ liệu để xác nhận tính đúng đắn của utf-8. Vì vậy, đây không phải là một O (1) hoạt động (mà người ta có thể nghĩ lúc đầu)
Zargony

64

Tôi thích String::from_utf8_lossy:

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

Nó biến các byte UTF-8 không hợp lệ thành và do đó không cần xử lý lỗi. Nó tốt cho khi bạn không cần nó và tôi hầu như không cần nó. Bạn thực sự nhận được một Stringtừ điều này. Nó sẽ giúp việc in ra những gì bạn nhận được từ máy chủ dễ dàng hơn một chút.

Đôi khi bạn có thể cần sử dụng into_owned()phương pháp này vì nó sao chép khi ghi.


3
Cảm ơn rất nhiều cho into_owned()lời đề nghị! Chính xác là tôi đang tìm kiếm (điều này làm cho nó trở thành một Stringgiá trị phù hợp mà bạn có thể trả về dưới dạng giá trị trả về từ một phương thức chẳng hạn).
Per Lundberg

47

Nếu bạn thực sự có một vectơ byte ( Vec<u8>) và muốn chuyển đổi thành a String, thì hiệu quả nhất là sử dụng lại phân bổ với 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
Cảm ơn! Tại sao hai câu trả lời khác lại bỏ qua câu hỏi?
Jehan,

1
@Jehan vì mọi người thường không giỏi đặt câu hỏi, đặc biệt là khi họ chưa quen với một ngôn ngữ. Rust phân biệt giữa một mảng , một lát cắt và một Vec, nhưng những người mới đến không biết sự khác biệt. Tuy nhiên, hãy chắc chắn rằng bạn đã tán thành tất cả các câu hỏi và câu trả lời có ích.
Shepmaster vào

Lưu ý rằng như được đề cập bởi @Bjorn Tipling, bạn có thể sử dụng String::from_utf8_lossythay thế ở đây, sau đó bạn không cần cuộc gọi mong đợi.
James Ray

2
Chỉnh sửa: Lưu ý rằng như được đề cập bởi @Bjorn Tipling, bạn có thể nghĩ rằng bạn có thể sử dụng String::from_utf8_lossythay thế ở đây, sau đó bạn không cần expectgọi, nhưng đầu vào cho đó là một phần của bytess ( &'a [u8]). OTOH, cũng có from_utf8_unchecked. "Nếu bạn chắc chắn rằng lát byte là UTF-8 hợp lệ và bạn không muốn phải chịu chi phí chuyển đổi, thì có một phiên bản không an toàn của hàm này [ from_utf8_lossy], from_utf8_uncheckedcó cùng hoạt động nhưng bỏ qua các bước kiểm tra. "
James Ray

Lưu ý rằng bạn có thể sử dụng &vec_of_bytesđể chuyển đổi lại thành một phần byte, như được liệt kê trong các ví dụ của from_utf8_lossy. doc.rust-lang.org/std/string/…
James Ray
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.