如何将u8向量打印为字符串?

31

这是我的代码:

let mut altbuf: Vec<u8> = Vec::new();

// Stuff here...

match stream.read_byte() {
    Ok(d) => altbuf.push(d),
    Err(e) => { println!("Error: {}", e); doneflag = true; }
}

for x in altbuf.iter() {
    println!("{}", x);
}

这段代码打印了正确的u8字节,但是我无论如何都想不出如何将纯u8字节的向量转换为字符串?在stackoverflow上类似问题的唯一其他答案假设你正在处理类型为&[u8]的向量。


欢迎来到 Stack Overflow!为了更好地提问,您可能需要重新措辞一下您的问题。您的标题使其听起来像您只想要 打印字节向量,这是相当容易的。您的正文使其看起来像您想将一系列字节视为 UTF-8 字符串,但您没有提及字节的编码方式。您也许还想包含一些关于您正在尝试做什么的详细信息;也许诸如 read_to_string 的解决方案可以解决您的真正问题。 - Shepmaster
4个回答

25
如果您查看String文档,您可以使用一些方法。有String::from_utf8,它接受Vec<u8>,还有String::from_utf8_lossy,它接受&[u8]
请注意,Vec<T>是一个拥有的可调整大小的包装器,封装了[T]。也就是说,如果您有一个Vec<u8>,则可以通过重新借用它(即&*some_vec)最轻松地将其转换为&[u8]。您也可以直接在Vec<T>上调用在&[T]上定义的任何方法(通常,对实现Deref特性的内容都是如此)。

嗨DK,你能否给我提供一个关于重新借用的澄清资源链接?更进一步地说,当我尝试执行println!("{}", &*altbuf);时,会出现“trait core::fmt::String is not implemented for type [u8]” 的错误提示。 - AAnderson
1
@AAnderson:你可能想要使用println!("{:?}", &*altbuf){}使用的是String格式化程序,适用于用户界面显示,而{:?}适用于任何内部表示。并非所有内容都有String格式化程序,但几乎所有内容都有Show格式化程序(这就是{:?}使用的内容)。关于重新借用的澄清:基本上只是在一个东西上调用Deref::deref并保留它返回的引用(通常,deref调用的结果会自动取消引用;额外的&可以防止这种情况发生)。我不知道还有更明确的解释。 - DK.
对于打印输出,创建一个String对象是不必要的。使用std::str::from_utf8就足够了。我留下了另一个包含示例代码的答案。 - youknowone

5
如果您的altbuf是一个u8向量,那么这应该可以工作:
println!("{:?}", altbuf);

这是我编辑过的一段代码,它做类似的事情:

let rebuilt: Vec<u8>;

unsafe {
    ret = proc_pidpath(pid, buffer_ptr, buffer_size);
    rebuilt = Vec::from_raw_parts(buffer_ptr as *mut u8, ret as usize, buffer_size as usize);
};

println!("Returned a {} byte string", ret);
println!("{:?}", rebuilt);

这个函数从通过 FFI 调用的 C 函数填充的缓冲区重新构建了一个 u8 值的向量,因此字节可以是任何内容,可能不是有效的 UTF-8 编码。

当我运行它时,输出结果为:

返回了一个长度为 49 的字符串

[47, 85, 115, 101, 114, 115, 47, 97, 110, 100, 114, 101, 119, 47, 46, 114, 98, 101, 110, 118, 47, 118, 101, 114, 115, 105, 111, 110, 115, 47, 49, 46, 57, 46, 51, 45, 112, 51, 57, 50, 47, 98, 105, 110, 47, 114, 117, 98, 121]

你可以使用 不同的格式化字符串{} 中打印十六进制、八进制等数字。

您可以使用String::from_utf8(rebuilt)从中获取一个String - 这可能会返回一个错误。
match String::from_utf8(rebuilt) {
    Ok(path) => Ok(path),
    Err(e) => Err(format!("Invalid UTF-8 sequence: {}", e)),
}

1
使用字节文字的例子可能比使用 FFI 和 unsafe 更清晰。您能展示一个将整个切片打印为十六进制数的例子吗?我不相信那会起作用,但很乐意被证明是错误的。 - Shepmaster
我认为这已经足够了,打印不同格式可以留给读者自己练习。 - Andrew Mackenzie

3
使用来自`std::io`的`write`方法:
use std::{io, io::Write};

fn main() -> io::Result<()> {
   io::stdout().write(b"March\n")?;
   Ok(())
}

它打印一个u8切片,也被称为字节串。

io::stdout


3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接