首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何组合std::str::lines和std::io::lines?

如何组合std::str::lines和std::io::lines?
EN

Stack Overflow用户
提问于 2016-05-04 12:55:27
回答 2查看 495关注 0票数 9

我想编写一个解析文本的函数,但是文本可能来自外部文件或内部&strparse函数可能如下所示:

代码语言:javascript
运行
复制
fn parse(lines: GenericLinesGenerator) {
   for line in lines {
       // parse content
   }
}

..。它可以这样被引用:

代码语言:javascript
运行
复制
use std::io::BufReader;
use std::fs::File;
let fin = BufReader::new(File::open("info.txt").expect("not found"));
parse(TransformFromIO(fin.lines()))

代码语言:javascript
运行
复制
let content: &'static str = "some\nlong\ntext";
parse(TransformFromStr(content.lines()))

是否有可能实现这样的parse函数?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-05-04 13:10:24

这两个迭代器不产生相同的值:

代码语言:javascript
运行
复制
impl<B: BufRead> Iterator for io::Lines<B> {
    type Item = Result<String>;
}
代码语言:javascript
运行
复制
impl<'a> Iterator for str::Lines<'a> {
    type Item = &'a str;
}

你必须设法处理这个差异。最重要的区别是io::Lines可能会失败。你的程序必须决定如何处理这个问题;我选择了放弃这个程序。

接下来您需要做的是接受可以转换为迭代器的任何类型,并且必须将从迭代器产生的值转换为您可以处理的类型。看来&str是共同的分母。

这是通过使用IntoIteratorBorrow解决的。

代码语言:javascript
运行
复制
use std::borrow::Borrow;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;

fn parse<I>(lines: I)
where
    I: IntoIterator,
    I::Item: Borrow<str>,
{
    for line in lines {
        println!("line: {}", line.borrow());
    }
}

fn main() {
    parse("alpha\nbeta\ngamma".lines());

    println!("----");

    let f = File::open("/etc/hosts").expect("Couldn't open");
    let b = BufReader::new(f);
    parse(b.lines().map(|l| l.expect("Bad line!")));
}

有关特征界限的更多信息,请查看http://doc.rust-lang.org/stable/book/部分在 clauses上。

票数 7
EN

Stack Overflow用户

发布于 2016-05-04 13:42:45

Borrow函数中使用parse绑定将允许您借用&str,但是如果您需要String值,更好的方法是使用Cow

使用line.borrow().to_string()获取一个String值总是会分配的,即使在使用文件中的行调用parse时(在本例中,lines.map生成String)。

使用line.into_owned()将在调用来自&str的行时分配,但当使用文件中的行调用时将不会分配(只会打开传递给Cow::OwnedString值)。

代码语言:javascript
运行
复制
use std::borrow::Cow;
use std::io::{BufReader, BufRead};
use std::iter::IntoIterator;
use std::fs::File;

fn parse<'a, I>(lines: I)
    where I: IntoIterator,
          I::Item: Into<Cow<'a, str>>
{
    for line in lines {
        let line: Cow<'a, str> = line.into();
        let line: String = line.into_owned();
        // or
        let line = line.into().into_owned()
        println!("{}", line);
    }
}

fn main() {
    let fin = BufReader::new(File::open("/etc/hosts").expect("cannot open file"));
    parse(fin.lines().map(|r| r.expect("file read failed")));

    let content: &'static str = "some\nlong\ntext";
    parse(content.lines());
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37028476

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档