我正在尝试将 ASCII 字节向量转换为 rust 字符串。我找到了一个std::str::from_utf8()
函数,它应该能够处理所有 ASCII 字符串。由于某种原因,它无法读取版权符号,如以下代码示例所示:
let buf = vec![0xA9, 0x41, 0x52, 0x54]; //©ART
println!(
"{}",
match std::str::from_utf8(&buf) {
Ok(x) => x,
Err(x) => {
println!("ERROR: {}", x);
"failed"
}
}
);
// > ERROR: invalid utf-8 sequence of 1 bytes from index 0
根据https://www.ascii-code.com/CP1252/169 0xA9
是一个有效的 ASCII 字符,根据https://www.compart.com/en/unicode/U+00A9也是一个有效的 UTF-8 字符。
我也尝试过String::from_utf8_lossy()
,但是�ART
结果却不是字符串应该有的样子。
是我遗漏了什么吗,或者这是 rust 处理 ASCII 方式的一个错误?
0xA9
不是 ASCII;ASCII 仅为 7 位编码,并且该值的第 8 位被设置。它可以被解释为扩展ASCII,这意味着需要预先了解字符集才能将其解释为“©”。您可以在链接中看到它在 Windows-1252 字符集中是“©”,但另一个链接显示它
0xA9
在代码页 437 字符集中是“⌐”。还有许多其他字符集。由于
0xA9
不是 ASCII,所以它不是 UTF8 - 至少它本身不是。第 8 位设置表示它是多字节序列的一部分,更重要的是,的位表示以0xA9
开头10xxxxxx
,这意味着它是多字节序列的中间(请参阅维基百科上的 UTF8 )。因此,任何遇到这种情况的 UTF8 解码器(没有前面的多字节起始字符)都会拒绝它。如果您想使用扩展的 ASCII 字符集并将其解码为 Rust 字符串,则需要以不同的方式对其进行解码。像encoding-rs这样的包可能可以做到这一点。