如果我不关心特定的编码,如何将u8切片打印为文本?

ide*_*n42 1 arrays string rust

u8在Rust中打印数组时,println!("{:?}", some_u8_slice);打印数值(应该如此).

在不假设任何特定编码的情况下,将字符格式化为字符串的最直接方法是什么.

像迭代字节字符串并将每个字符写入stdout (没有那么多麻烦)的东西.

可以使用Rusts来完成format!吗?

否则,打印u8切片最方便的方法是什么?

Mat*_*eck 8

最简单的方法是stdout().write_all(some_u8_slice).这将简单地输出字节,而不考虑它们的编码.这对于二进制数据或某些未知编码中要保留原始编码的文本非常有用.

如果您想将数据视为字符串,并且您知道编码是UTF-8(或UTF-8子集,如ASCII),那么您可以这样做:

use std::str;

fn main() {
    let some_utf8_slice = &[104, 101, 0xFF, 108, 111];
    if let Ok(s) = str::from_utf8(some_utf8_slice) {
        println!("{}", s);
    }
}
Run Code Online (Sandbox Code Playgroud)

这将在打印前检查数据是否为有效UTF-8.


the*_*472 6

如果您只想将未转义的原始字节铲到标准输出,这在将输出重定向到管道或文件时特别有用,那么以下应该完成这项工作:

let mut out = std::io::stdout();
out.write_all(slice)?;
out.flush()?;
Run Code Online (Sandbox Code Playgroud)

flush是必要的,因为write_all紧随其后的程序中止可能无法将字节传递给底层文件描述符。


Bur*_*hi5 5

如果我不能假设一个特定的编码,我通常这样做的方式是使用该std::ascii::escape_default函数.基本上,它会显示大多数ASCII字符,然后逃避其他所有字符.缺点是,即使您的严格部分是正确的UTF-8,您也不会看到所有可能的Unicode代码点,但它适用于大多数用途:

use std::ascii::escape_default;
use std::str;

fn show(bs: &[u8]) -> String {
    let mut visible = String::new();
    for &b in bs {
        let part: Vec<u8> = escape_default(b).collect();
        visible.push_str(str::from_utf8(&part).unwrap());
    }
    visible
}

fn main() {
    let bytes = b"foo\xE2\x98\x83bar\xFFbaz";
    println!("{}", show(bytes));
}
Run Code Online (Sandbox Code Playgroud)

输出: foo\xe2\x98\x83bar\xffbaz

另一种方法是将内容丢失地解码成字符串并打印出来.如果存在任何无效的UTF-8,您将获得Unicode替换字符而不是原始字节的十六进制转义,但您将看到所有有效的UTF-8编码的Unicode代码点:

fn show(bs: &[u8]) -> String {
    String::from_utf8_lossy(bs).into_owned()
}

fn main() {
    let bytes = b"foo\xE2\x98\x83bar\xFFbaz";
    println!("{}", show(bytes));
}
Run Code Online (Sandbox Code Playgroud)

输出: foo?bar?baz