【问题标题】:Is this the right way to read lines from file and split them into words in Rust?这是从文件中读取行并将它们拆分为 Rust 中的单词的正确方法吗?
【发布时间】:2014-08-30 10:40:01
【问题描述】:

编者注:此代码示例来自 Rust 1.0 之前的版本,在语法上不是有效的 Rust 1.0 代码。此代码的更新版本会产生不同的错误,但答案仍然包含有价值的信息。

我已经实现了以下方法以从二维数据结构的文件中返回单词:

fn read_terms() -> Vec<Vec<String>> {
    let path = Path::new("terms.txt");
    let mut file = BufferedReader::new(File::open(&path));
    return file.lines().map(|x| x.unwrap().as_slice().words().map(|x| x.to_string()).collect()).collect();
}

这是 Rust 中正确、惯用且有效的方式吗?我想知道是否需要经常调用collect(),以及是否有必要在这里调用to_string() 来分配内存。也许应该以不同的方式定义返回类型以更加惯用和高效?

【问题讨论】:

    标签: rust


    【解决方案1】:

    有一种更短、更易读的方法从文本文件中获取单词。

    use std::io::{BufRead, BufReader};
    use std::fs::File;
    
    let reader = BufReader::new(File::open("file.txt").expect("Cannot open file.txt"));
    
    for line in reader.lines() {
        for word in line.unwrap().split_whitespace() {
            println!("word '{}'", word);
        }
    }
    

    【讨论】:

      【解决方案2】:

      您可以改为将整个文件作为单个 String 读取,然后构建一个指向内部单词的引用结构:

      use std::io::{self, Read};
      use std::fs::File;
      
      fn filename_to_string(s: &str) -> io::Result<String> {
          let mut file = File::open(s)?;
          let mut s = String::new();
          file.read_to_string(&mut s)?;
          Ok(s)
      }
      
      fn words_by_line<'a>(s: &'a str) -> Vec<Vec<&'a str>> {
          s.lines().map(|line| {
              line.split_whitespace().collect()
          }).collect()
      }
      
      fn example_use() {
          let whole_file = filename_to_string("terms.txt").unwrap();
          let wbyl = words_by_line(&whole_file);
          println!("{:?}", wbyl)
      }
      

      这将以更少的开销读取文件,因为它可以将文件吞入单个缓冲区,而使用BufReader 读取行意味着大量复制和分配,首先进入BufReader 内的缓冲区,然后进入一个新的为每一行分配String,然后为每个单词分配一个新的String。它也将使用更少的内存,因为单个大 String 和引用向量比许多单独的 Strings 更紧凑。

      一个缺点是你不能直接返回引用的结构,因为它不能超过堆栈帧,它保存着单个大的String。在上面的example_use 中,我们必须将大的String 放入let 以便调用words_by_line。可以使用不安全的代码并将String 和引用包装在私有结构中来解决此问题,但这要复杂得多。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-17
        • 1970-01-01
        • 2016-09-02
        • 2013-05-31
        • 1970-01-01
        • 2019-04-27
        相关资源
        最近更新 更多