我正在创建一个简单的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

这意味着什么?如何修复?

推荐答案

documentation for String人》将其描述为:

UTF-8编码的可增长字符串.

Wikipedia definition of UTF-8分将为你提供大量的背景知识.简而言之,计算机使用一个叫做byte的单元来表示数据.不幸的是,这些用字节表示的数据块没有内在意义;这必须从外部提供.UTF-8是解释字节序列的一种方式,JPEG等文件格式也是如此.

与大多数文本编码一样,UTF-8有特定的要求,字节序列为validinvalid.无论您试图加载的是什么图像,它都包含无法解释为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字符串",所以我们可以编写更安全的程序,因为我们知道这个不变量总是正确的.我们不必在整个程序中不断判断以"确保"它仍然是字符串.

Rust相关问答推荐

WebDriver等待三十四?(Rust Se)

无需通过ASIO输入音频,并使用cpal进行反馈示例

文档示例需要导入相关的 struct ,但仅在运行测试时.这是故意的行为吗?

当两者都有效时,为什么Rust编译器建议添加';&;而不是';*';?

如果成员都实现特征,是否在多态集合上实现部分重叠的特征?

在Rust中有没有办法在没有UB的情况下在指针和U64之间进行转换?

在跨平台应用程序中使用std::OS::Linux和std::OS::Windows

如何在 struct 的自定义序列化程序中使用serde序列化_WITH

函数内模块的父作用域的访问类型

S,一般性状和联想型性状有什么不同?

处理带有panic 的 Err 时,匹配臂具有不兼容的类型

Cargo.toml:如何有条件地启用依赖项功能?

为什么我可以使用 &mut (**ref) 创建两个实时 &mut 到同一个变量?

为什么Rust中无法推断生命周期?

没有明确地说return会产生错误:match arms have incompatible types

Rust 中的方法调用有什么区别?

为什么 File::read_to_end 缓冲区容量越大越慢?

具有生命周期和以后引用的可变方法

隐式类型闭包的错误生命周期推断

Rust 内联 asm 中的向量寄存器:不能将 `Simd` 类型的值用于内联汇编