我想读取一个文本文件并将所有行转换为 int 值。我用这个代码。但我真正怀念的是一种“好的”错误处理方式。
use std::{
fs::File,
io::{prelude::*, BufReader},
path::Path
};
fn lines_from_file(filename: impl AsRef<Path>) -> Vec<i32> {
let file = File::open(filename).expect("no such file");
let buf = BufReader::new(file);
buf.lines()
.map(|l| l.expect("Could not parse line"))
.map(|l:String| l.parse::<i32>().expect("could not parse int"))
.collect()
}
Run Code Online (Sandbox Code Playgroud)
问题:如何进行正确的错误处理?上面的例子是“好的 Rust 代码”吗?或者我应该使用这样的东西:
fn lines_from_file(filename: impl AsRef<Path>) -> Vec<i32> {
let file = File::open(filename).expect("no such file");
let buf = BufReader::new(file);
buf.lines()
.map(|l| l.expect("Could not parse line"))
.map(|l:String| match l.parse::<i32>() {
Ok(num) => num,
Err(e) => -1 //Do something here
}).collect()
}
Run Code Online (Sandbox Code Playgroud)
Jer*_*eke 12
您实际上可以收集到Result<T, E>.
查看文档
这样你就可以收集到一个Result<Vec<i32>, MyCustomErrorType>. 当您将迭代器转换为返回Result<i32, MyCustomErrorType>. 迭代在Err您第一次映射时停止。
这是您的工作代码示例。我使用thiserror箱进行错误处理
use std::{
fs::File,
io::{prelude::*, BufReader},
num::ParseIntError,
path::Path,
};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum LineParseError {
#[error("Failed to read line")]
IoError(#[from] std::io::Error),
#[error("Failed to parse int")]
FailedToParseInt(#[from] ParseIntError),
}
fn lines_from_file(filename: impl AsRef<Path>) -> Result<Vec<i32>, LineParseError> {
let file = File::open(filename).expect("no such file");
let buf = BufReader::new(file);
buf.lines().map(|l| Ok(l?.parse()?)).collect()
}
Run Code Online (Sandbox Code Playgroud)
通过分解这行代码来对代码的工作原理进行一些小解释:
buf.lines().map(|l| Ok(l?.parse()?)).collect()
Run Code Online (Sandbox Code Playgroud)
Result<Vec<i32>, LineParseError>因为函数的返回类型是Result<Vec<i32>, LineParseError>l?这使得映射方法返回 anErr如果l结果包含 an Err,#[from]属性 onLineParseError::IoError负责转换.parse()?工作方式相同:#[from]onLineParseError::FailedToParseInt负责转换Ok(...)最后但并非最不重要的一点是,当映射成功时,我们的方法必须返回,这使得collectinto 成为Result<Vec<i32>, LineParseError>可能。| 归档时间: |
|
| 查看次数: |
3875 次 |
| 最近记录: |