首页 > 解决方案 > 从文件中取出数字并放入 Vec但不断出错

问题描述

代码:

use std::io::Read;

fn main() {
  let mut file = std::fs::File::open("numbs").unwrap();
  let mut contents = String::new();
  file.read_to_string(&mut contents).unwrap();
  let mut v: Vec<i32> = Vec::new();
  for s in contents.lines() {
      v.push(s.parse::<i32>().unwrap());
  }
}

错误:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: Empty }', src/libcore/result.rs:1165:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

标签: fileparsingrust

解决方案


最有可能的是,文件末尾有一个尾随换行符\n,即最后一行是空的。您的文件中间可能还有空行。

为您的用例解决此问题的最简单方法是忽略空行:

for s in contents.lines() {
    if !s.is_empty() {
        v.push(s.parse::<i32>().unwrap());
    }
}

但是,如果你不能保证它永远不会恐慌,那么只做unwrap一个通常不是一个好主意。Result一个更强大的解决方案是Result适当地处理每个可能的结果。此解决方案的另一个优点是它不仅会忽略空行,还会忽略无法解析为i32. 这是否是您想要的,或者您是否希望明确处理此错误取决于您。在下面的示例中,我们将使用 if-let 仅在将值成功解析为 时才将值插入到向量中i32

for s in contents.lines() {
    if let Ok(i) = s.parse::<i32>() {
        v.push(i);
    }
}

旁注:您不需要将整个文件读入字符串然后逐行解析。请参阅在 Rust 中逐行读取大文件以了解如何更惯用地实现这一点

结合上述观点和 and 的使用flattenflat_map我们可以将逻辑大大简化为:

use std::fs::File;
use std::io::{BufRead, BufReader};

fn main() {
    let file = File::open("numbs").unwrap();
    let v: Vec<i32> = BufReader::new(file)
                          .lines()
                          .flatten()                             // gets rid of Err from lines
                          .flat_map(|line| line.parse::<i32>())  // ignores Err variant from Result of str.parse
                          .collect();
}

推荐阅读