使用 BufReader 读取 Rust 中的 JSON 文件时出错:特征绑定结果:std::io::Read 不满足

nil*_*kar 2 file-io json rust

我正在尝试从文件中读取 JSON:

use std::error::Error;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;

impl Params {
    pub fn new(raw_opt2: opt::Opt, path: String) -> Self {
        // Open the file in read-only mode with buffer.
        let file = File::open(path);
        let reader = BufReader::new(file);
        Self {
            opt_raw: raw_opt2,
            module_settings: serde_json::from_reader(reader).unwrap(),
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但我收到一个错误:

error[E0277]: the trait bound `std::result::Result<std::fs::File, std::io::Error>: std::io::Read` is not satisfied
  --> src\params.rs:20:37
   |
20 |         let reader = BufReader::new(file);
   |                                     ^^^^ the trait `std::io::Read` is not implemented for `std::result::Result<std::fs::File, std::io::Error>`
   |
   = note: required by `std::io::BufReader::<R>::new`
Run Code Online (Sandbox Code Playgroud)

mat*_*tiu 6

File ::open操作返回Result- 表示打开操作可能成功也可能失败。

与许多其他语言相比,这是 Rust 的一个突出特性;它试图强迫你处理错误。代替:

  • C - 只返回一个 int
  • Python - 异常(尝试:最后:)
  • C++ - 异常(需要 libstdc++ 运行时)

正如您所期望的,这会导致一开始就需要更多的编程时间,但总的来说,麻烦会少得多,程序质量也会更高。

在该行之后,let file = File::open(path);您必须处理结果。

如果您不在乎,并且希望在无法打开文件时使程序崩溃:

let file = File::open(path).unwrap();
Run Code Online (Sandbox Code Playgroud)

为了在崩溃时提供更好的错误消息:

let file = File::open(path).expect("Unable to open file");
Run Code Online (Sandbox Code Playgroud)

正确地做到这一点 -阅读 Rust 书

最有可能的是,您希望Result从函数中返回一个self。然后你可以像这样重写它(使用 a match):

impl Params {
    pub fn new(raw_opt2: opt::Opt, path: String) -> Result<Self, std::io::Error> {
        // Open the file in read-only mode with buffer.
        match File::open(path) {
            Ok(file) => {
                let reader = BufReader::new(file);
                Ok(Self {
                    opt_raw: raw_opt2,
                    module_settings: serde_json::from_reader(reader).unwrap(),
                })
            }
            Err(err) => Err(err),
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

..或更实用的方式:

impl Params {
    pub fn new(raw_opt2: opt::Opt, path: String) -> Result<Self, std::io::Error> {
        // Open the file in read-only mode with buffer.
        File::open(path).map(|file| {
            let reader = BufReader::new(file);
            Self {
                opt_raw: raw_opt2,
                module_settings: serde_json::from_reader(reader).unwrap(),
            }
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:

现在我一般使用这两个库进行错误管理:

  • thiserror当我编写库并创建自己的错误类型时
  • 无论如何,在编写应用程序或脚本或测试时可以轻松处理所有库错误。

..当然我没有提到?运算符,这使得处理结果和选项变得更加容易。