rust - 从标准输入读取整行,包括 \n 直到文件结束
问题描述
我想将此 Python 代码转换为 Rust:
for line in sys.stdin:
do something to the whole line including \n
但我只能找到读取单个完整行(包括\n
)的示例或不读取\n
.
看起来这应该是世界上最简单的,但我一直找不到。
解决方案
Python和Rust都为迭代文件中的行提供了便利的 API,它们只是选择了便利性与完整性的不同权衡。Rust 选择了额外的便利性并以能够区分最后一行是否以终止符结尾为代价去除换行符。Python 选择了相反的方式,代价是所有行解析器都必须考虑 final \n
,并且还考虑到它是optional。
但BufRead::lines()
只是一个方便的AP;如果它不能满足您的需求,您可以随时使用较低级别的read_line()
方法:
let mut line = String::new();
while input.read_line(&mut line)? != 0 {
let line = std::mem::take(&mut line);
// ...
}
如果你在多个地方使用这种代码,或者只是想要for
循环的便利,你可以将它抽象成一个返回迭代器的实用函数,例如:
fn full_lines(mut input: impl BufRead) -> impl Iterator<Item = io::Result<String>> {
std::iter::from_fn(move || {
let mut vec = String::new();
match input.read_line(&mut vec) {
Ok(0) => None,
Ok(_) => Some(Ok(vec)),
Err(e) => Some(Err(e)),
}
})
}
然后您可以使用for
类似于 Python 中的循环:
for line in full_lines(io::stdin().lock()) {
let line = line?;
// ...
}
通过额外的努力,甚至可以full_lines
在任何实现的东西上创建一个方法BufRead
:
trait FullLines: BufRead + Sized {
fn full_lines<'a>(self) -> Box<dyn Iterator<Item = io::Result<String>> + 'a>
where
Self: 'a,
{
Box::new(full_lines(self))
}
}
// Provide a blanket implementation of FullLines for any T
// that implements BufRead
impl<T: BufRead> FullLines for T {}
// Usage:
use FullLines;
for line in io::stdin().lock().full_lines() {
let line = line?;
// ...
}
推荐阅读
- java - 在vertx中编写asyc代码时有什么方法可以避免重复代码?
- ssl - 如何在没有域名的情况下实现浏览器友好的 SSL/HTTPS?
- xpages - 如何使用 onChange 事件 SSJS 防止完全刷新
- python - 在 Windows 上安装 PyAudio
- angular - 使用 docker 构建 Angular 项目并提取 dist 文件夹
- python - 在美丽的汤中用文字刮掉表情符号
- excel - 无法使用 vba 从菜单按钮注销
- python - 如何测试 aiohttp 服务器?
- database - 不同表结构的数据库迁移
- mysql - 无法停止 mysql 服务器也无法启动它