如何在跳过与特定模式匹配的行时从文件中读取行?

时间:2019-05-24 15:34:38

标签: file-io rust borrow-checker

我想逐行读取文件:

  • 跳过以'#'开头的行
  • 如果它们不是以“#”开头,​​则打印(或以其他方式使用它们)

我尝试了两种不同的方法,但我认为我对Rust的理解不足以正确编写它。

方法1

我将文件保存到BufReader,还使用BufReader通过引用获取了by_ref

我的问题是我不知道怎么说“我不想只读取第一个字节就修改行”。我还尝试了字符串的字节表示形式,但是对于代码示例来说看起来很丑

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

fn main() -> io::Result<()> {
    let fname = "/etc/hosts";

    let file = File::open(fname)?;
    let mut br = BufReader::new(file);
    for line in br.by_ref().lines() {
        if line.unwrap().starts_with("#") {
            continue;
        }
        println!("{}", line?);
    }

    Ok(())
}

每次都会出现编译器响应:“我无法给您该行,因为它已被移动以进行检查...”。

error[E0382]: use of moved value: `line`
  --> src/main.rs:15:24
   |
11 |     for line in br.by_ref().lines() {
   |         ---- move occurs because `line` has type `std::result::Result<std::string::String, std::io::Error>`, which does not implement the `Copy` trait
12 |         if line.unwrap().starts_with("#") {
   |            ---- value moved here
...
15 |         println!("{}", line?);
   |                        ^^^^ value used here after move

方法2

我认为我可以使用过滤器。我不想走这样的路,因为大多数有更多顺序编程习惯的人不喜欢对这些操作(例如文件操作)使用功能模式。我们更喜欢控制缓冲区的大小,以及何时发生什么情况,而功能方法通常会使难度变得更大。

我以为我应该发布的信息是,我知道这可以通过功能性的方式来完成,但是在我编写并运行它之后,它又遇到了同样的问题...

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

fn main() -> io::Result<()> {
    let fname = "/etc/hosts";

    let file = File::open(fname)?;
    let lines: io::Result<std::string::String> = BufReader::new(file)
        .lines()
        .filter(|x| x.unwrap().starts_with('#'))
        .collect();

    for line in lines {
        println!("{}", line);
    }

    Ok(())
}

我遇到一个错误:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:12:21
   |
12 |         .filter(|x| x.unwrap().starts_with('#'))
   |                     ^ cannot move out of borrowed content

将lambda参数x更改为引用将导致借入,这将引起编译器的另一响应:cannot move out of borrowed content

是否有任何简单的方法可以编写此类模式,而无需每次都复制值?

0 个答案:

没有答案