我试图在Rust中编写简单的TCP/IP客户端,我需要打印出我从服务器获得的缓冲区。
我如何转换一个Vec<u8>(或一个&[u8])到一个字符串?
我试图在Rust中编写简单的TCP/IP客户端,我需要打印出我从服务器获得的缓冲区。
我如何转换一个Vec<u8>(或一个&[u8])到一个字符串?
将字节片转换为字符串片(假设为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);
}
转换是就地进行的,不需要分配。如果需要,可以通过在字符串片上调用.to_owned()来从字符串片创建一个String(其他选项也可用)。
如果您确定字节片是有效的UTF-8,并且不想引起有效性检查的开销,那么这个函数有一个不安全的版本from_utf8_unchecked,它具有相同的行为,但跳过了检查。
如果你需要一个String而不是&str,你也可以考虑String::from_utf8。
转换函数的标准库引用:
std:: str:: from_utf8 std:: str:: from_utf8_unchecked std:: string:字符串::from_utf8
我更喜欢String::from_utf8_lossy:
fn main() {
let buf = &[0x41u8, 0x41u8, 0x42u8];
let s = String::from_utf8_lossy(buf);
println!("result: {}", s);
}
它将无效的UTF-8字节转换为-,因此不需要任何错误处理。当你不需要它的时候它很好,而我几乎不需要它。你实际上从这里得到一个字符串。它应该使您更容易打印出从服务器获取的内容。
有时您可能需要使用into_owned()方法,因为它是在写入时克隆的。
如果你实际上有一个字节向量(Vec<u8>),并且想要转换为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);
}
在我的例子中,我只需要将数字转换为字符串,而不是根据某种编码将数字转换为字母,所以我这样做了
fn main() {
let bytes = vec![0x41, 0x42, 0x43];
let s = format!("{:?}", &bytes);
println!("{}", s);
}
为了最优地将可能包含非UTF-8字符/字节序列的Vec<u8>转换为UTF-8 String,而不需要任何不必要的分配,您需要乐观地尝试调用String::from_utf8(),然后求助于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();
其他答案中建议的方法将导致内存中有两个自有缓冲区,即使在愉快的情况下(向量中有有效的UTF-8数据):一个是原始的u8字节,另一个是拥有其字符的String形式。这种方法将尝试使用Vec<u8>并直接将其封送为Unicode字符串,只有在失败时才会为包含丢失的UTF-8解码输出的新字符串分配空间。