“Stream did not contain valid UTF-8” 是什么意思?(涉及IT技术)

15

我正在创建一个简单的HTTP服务器。我需要读取被请求的图像并将其发送到浏览器。我正在使用以下代码:

fn read_file(mut file_name: String) -> String {
    file_name = file_name.replace("/", "");
    if file_name.is_empty() {
        file_name = String::from("index.html");
    }

    let path = Path::new(&file_name);
    if !path.exists() {
        return String::from("Not Found!");
    }
    let mut file_content = String::new();
    let mut file = File::open(&file_name).expect("Unable to open file");
    let res = match file.read_to_string(&mut file_content) {
        Ok(content) => content,
        Err(why) => panic!("{}",why),
    };

    return file_content;
}

如果请求的文件是基于文本的,则此方法可行,但是当我想要读取图像时,我会收到以下消息:

流不包含有效的UTF-8

这是什么意思,如何修复?


2
UTF-8是使用字节编码字符串的一种方式。与大多数编码方式一样,不是每个字节序列都对应于可以解释为UTF-8字符串的内容。由于您的文件是图像,您可能只想读取原始字节。bytesread_to_end可能会有所帮助。 - Alec
1个回答

21

String的文档将其描述为:

一个UTF-8编码的可增长字符串。

UTF-8的维基百科定义可以让你了解更多有关它的背景。简而言之,计算机使用称为字节的单位来表示数据。不幸的是,用字节表示的这些数据块没有本质意义;必须从外部提供。UTF-8是解释一系列字节的方式之一,像JPEG等文件格式也是如此。

像大多数文本编码一样,UTF-8有特定的要求和字节序列是有效无效的。你尝试加载的任何图像都包含一个不能被解释为UTF-8字符串的字节序列;这就是错误消息告诉你的。


为了修复它,你不应该使用String来保存任意集合的字节。在Rust中,最好使用Vec来表示它们:

fn read_file(mut file_name: String) -> Vec<u8> {
    file_name = file_name.replace("/", "");
    if file_name.is_empty() {
        file_name = String::from("index.html");
    }

    let path = Path::new(&file_name);
    if !path.exists() {
        return String::from("Not Found!").into();
    }
    let mut file_content = Vec::new();
    let mut file = File::open(&file_name).expect("Unable to open file");
    file.read_to_end(&mut file_content).expect("Unable to read");
    file_content
}
为了宣传一下,这就是为什么 Rust 是一门好的语言的一个很棒的方面。因为有一种类型可以代表“一组字节,保证是有效的 UTF-8 字符串”,我们可以编写更安全的程序,因为我们知道这个不变量总是成立的。我们不必在程序中一遍又一遍地检查以“确保”它仍然是一个字符串。

谢谢你的回答。我使用了你的例子,但现在我遇到了这个错误:无效的 UTF-8:索引0附近的无效字节 - Saeed M.
@smoqadam,这很难相信。现在已经没有显示任何代码尝试将任意字节转换为UTF-8了。也许您有一些代码可以获取返回的Vec并尝试将其再次转换为String?它们仍然是相同的一组字节;它们永远无法在当前状态下转换为UTF-8。 - Shepmaster
是的,我需要将它转换成字符串并发送到浏览器。怎么做呢? - Saeed M.
@smoqadam 你不能将图像的原始数据视为UTF-8字符串。好消息是,HTTP 1.0协议(以及1.1和可能的2.0)不要求请求/响应的主体数据必须是UTF-8字符串。只要指定适当的标头,发送原始字节是完全有效的。 - Shepmaster
再次感谢。我是 Rust 的新手,很困惑。你能给我一个示例,如何读取一张图片并将其返回到浏览器? - Saeed M.
1
@smoqadam,这取决于你使用的库。Shepmaster的最后一条评论非常清晰,但需要对HTTP协议的工作方式有一定的背景知识。也许你应该考虑阅读关于HTTP协议的资料? - aochagavia

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