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

Error while reading JSON file in Rust using BufReader: the trait bound Result: std::io::Read is not satisfied

我正在尝试从文件中读取 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(),
        }
    }
}

但是我收到一个错误:

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`

File::open operation returns a Result - 表示打开操作可能成功或失败。

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

  • C - 只是 return 一个整数
  • Python - 异常(尝试:finally:)
  • C++ - 异常(需要 libstdc++ 运行时)

如您所料,这会在开始时增加编程时间,但总的来说 很多 更少的麻烦和更高质量的程序。

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

如果你不在乎,想在文件打不开时崩溃:

let file = File::open(path).unwrap();

为了在崩溃时做出更好的错误信息:

let file = File::open(path).expect("Unable to open file");

正确地做 - read the Rust book

很可能,您会希望 return 从您的函数中 Result 自己。然后你可以像这样重写它(使用 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),
        }
    }
}

.. 或者更实用的方式:

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(),
            }
        })
    }
}

更新:

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

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

.. 当然我没有提到 the ? operator,这使得处理结果和选项变得容易得多。