【问题标题】:How can I match on a specific io::Error type?如何匹配特定的 io::Error 类型?
【发布时间】:2015-02-13 02:54:48
【问题描述】:

我试图一次读取一个文件直到结束 2 个字节,我想捕获 EOF 错误:

use byteorder::{BigEndian, ReadBytesExt}; // 1.3.4
use std::fs::File;

fn main() {
    let filename = "/etc/hosts";
    let mut file = File::open(filename).expect("Cannot open file");
    loop {
        let binary = match file.read_u16::<BigEndian>() {
            Ok(binary) => binary,
            Err(e) => panic!("Can't read from file: {}, err {}", filename, e),
            // Can I catch the EOF error here?
        };
        println!("{:?}", binary);
    }
}

【问题讨论】:

标签: error-handling rust


【解决方案1】:

我发现...

Err(e) => match e.kind() {
    EndOfFile => break,
    SomeOtherError => do_something(),
    _ => panic!("Can't read from file: {}, err {}", filename, e),
},

};

...比...更具可读性

Ok(binary) => binary,
Err(ref e) if e.kind() == EndOfFile => break,
Err(ref e) if e.kind() == SomeOtherError => do_something(),
Err(e) => panic!("Can't read from file: {}, err {}", filename, e),

(我不确定我们可能会遇到什么其他错误...)

在比赛守卫可能不一样的其他情况下——我们重复e.kind()的方式——我们不能使用嵌套的match

这适用于 Rust 1.25。

【讨论】:

    【解决方案2】:

    这适用于 Rust 1.17.0 版(并且可能回到 Rust 1.0):

    let binary = match file.read_u16::<BigEndian>() {
        Err(ref e) if e.kind() == std::io::ErrorKind::UnexpectedEof => break,
        Err(e) => panic!("Can't read from file: {}, err {}", filename, e),
        Ok(binary) => binary,
    };
    

    【讨论】:

      【解决方案3】:

      编者注:此代码示例来自 Rust 1.0 之前的版本,不适用于稳定的 Rust 1.0 io::Error。嵌套模式匹配的概念仍然适用于其他上下文。

      您可以将种类作为模式的一部分进行匹配,使用模式匹配的一些更高级的功能:

      Err(IoError { kind: IoErrorKind::EndOfFile, .. }) => break,
      Err(e) => panic!("Can't read from file: {}, err {}", filename, e),
      

      第一个变体的意思是“一个Err 包含一个IoError,其中kindIoErrorKind::EndOfFile,所有其他字段都是你喜欢的”。第二个则表示“任何其他Err,将包含的值绑定到变量名e”。

      【讨论】:

      • 这还能用吗? IoError 这些天看起来不同了,我最接近的仍然导致 error[E0026]: struct std::io::Error does not have a field named kind
      • @sarnold: std::io::Error 现在隐藏了它的字段,所以你不能编辑 Error 对象的类型;但是,它确实有一个 method kind() 可以返回种类。现在我推荐类似Err(ref e) if e.kind() == io::ErrorKind::EndOfFile =&gt; break,的东西。
      • 谢谢,很高兴知道我没有遗漏一些明显的东西。
      • 旁注:如今,rust 文档明确指出“不再需要读取的字节”应始终为 Ok(0) 而不是 ErrorKind::EndOfFile
      【解决方案4】:

      我想通了。我更改了这一行以检查错误类型!希望这对其他人有所帮助。

      Err(e) => if e.kind == IoErrorKind::EndOfFile { break } else { panic!("Can't read from file: {}, err {}", filename, e) },
      

      【讨论】:

      【解决方案5】:

      这是一个匹配MySQL IoError的例子:

      match pool.prep_exec("SELECT SLEEP(10)", ()) {
          Ok(_) => (),
          Err(mysql::Error::IoError(e)) => {
              eprintln!("IoError: {}", e);
              do_something();
          }
          Err(e) => {
              eprintln!("{}", e);
              return;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-03-24
        • 2017-09-16
        • 2013-05-04
        • 2020-02-19
        • 2022-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多