为什么《Rust书》中的BufRead的高效示例高效?

huangapple go评论61阅读模式
英文:

Why is the efficient example of BufRead in the Rust book, efficient?

问题

以下是您要翻译的内容:

"The rust book gives two (relevant here) examples of how to use BufRead. They first give a 'beginner friendly' example, before going onto a more 'Efficient method'.

The beginner friendly example reads a file line by line:

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

fn read_lines(filename: String) -> io::Lines<BufReader<File>> {
    // Open the file in read-only mode.
    let file = File::open(filename).unwrap(); 
    // Read the file line by line, and return an iterator of the lines of the file.
    return io::BufReader::new(file).lines(); 
}

fn main() {
    // Stores the iterator of lines of the file in lines variable.
    let lines = read_lines('./hosts'.to_string());
    // Iterate over the lines of the file, and in this case print them.
    for line in lines {
        println!("{}", line.unwrap());
    }
}

The 'efficient method' does nearly the same:

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

fn main() {
    // File hosts must exist in the current path before this produces output
    if let Ok(lines) = read_lines('./hosts') {
        // Consumes the iterator, returns an (Optional) String
        for line in lines {
            if let Ok(ip) = line {
                println!("{}", ip);
            }
        }
    }
}

// The output is wrapped in a Result to allow matching on errors
// Returns an Iterator to the Reader of the lines of the file.
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>, {
    let file = File::open(filename)?;
    Ok(io::BufReader::new(file).lines())
}

The rust book states for the latter:

This process is more efficient than creating a String in memory, especially when working with larger files.

While the latter is slightly cleaner, using if let instead of unwrap, why is it more efficient to return a Result? I assume that once we unwrap the iterator in the second example (in if let Ok(lines) = read_lines('./hosts')), performance-wise it should be identical to the first example. Why does it differ then? Why does the iterator in the second example return a result each time?"

英文:

The rust book gives two (relevant here) examples of how to use BufRead.
They first give a "beginner friendly" example, before going onto a more "Efficient method".

The beginner friendly example reads a file line by line:

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

fn read_lines(filename: String) -&gt; io::Lines&lt;BufReader&lt;File&gt;&gt; {
    // Open the file in read-only mode.
    let file = File::open(filename).unwrap(); 
    // Read the file line by line, and return an iterator of the lines of the file.
    return io::BufReader::new(file).lines(); 
}

fn main() {
    // Stores the iterator of lines of the file in lines variable.
    let lines = read_lines(&quot;./hosts&quot;.to_string());
    // Iterate over the lines of the file, and in this case print them.
    for line in lines {
        println!(&quot;{}&quot;, line.unwrap());
    }
}

The "efficient method" does nearly the same:

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

fn main() {
    // File hosts must exist in current path before this produces output
    if let Ok(lines) = read_lines(&quot;./hosts&quot;) {
        // Consumes the iterator, returns an (Optional) String
        for line in lines {
            if let Ok(ip) = line {
                println!(&quot;{}&quot;, ip);
            }
        }
    }
}

// The output is wrapped in a Result to allow matching on errors
// Returns an Iterator to the Reader of the lines of the file.
fn read_lines&lt;P&gt;(filename: P) -&gt; io::Result&lt;io::Lines&lt;io::BufReader&lt;File&gt;&gt;&gt;
where P: AsRef&lt;Path&gt;, {
    let file = File::open(filename)?;
    Ok(io::BufReader::new(file).lines())
}

The rust book states for the latter:
> This process is more efficient than creating a String in memory especially working with larger files.

While the latter is slightly cleaner, using if let instead of unwrap, why is it more efficient to return a Result?
I assume that once we unwrap the iterator in the second example (in if let Ok(lines) = read_lines(&quot;./hosts&quot;)), that performance wise it should be identical to the first example.
Why does it differ then?
Why does the iterator in the second example return a result each time?

答案1

得分: 1

你说得对,"初学者友好" 的方法并不比较高效,并且不会在内存中"创建一个字符串"。看起来我们中的许多人都感到困惑。

目前至少有两个拉取请求试图解决这种困惑,也许你可以评论你偏好的拉取请求:

这两个拉取请求都修改了初学者友好的方法,使用read_to_string而不是BufRead

read_to_string使初学者友好的方法"不高效",正如#1641中的文本所建议的

read_to_string还提供了一个实际示例"在内存中创建一个字符串"。有趣的是,这个短语"在内存中创建一个字符串"自从第一个提交以来就一直存在...

...一开始这个短语只是描述了一个假设的方法,这种方法会不那么高效...

...然后#1641提供了一些初学者友好方法的实际代码... 但它并不比较高效!...

...直到#1679或#1681之前,从未有实际代码展示不那么高效的方法!

更新 #1679已合并到主分支

英文:

You're right the "beginner friendly" method is no less efficient, and does not "create a String in memory". It seems like many of us were confused.

There are currently at least two pull requests which try to fix the confusion, maybe you can comment on the pull request you prefer:

Both of these pull requests modify the beginner friendly method to use read_to_string instead of BufRead.

read_to_string makes the beginner friendly method "NOT efficient" as the text from #1641 suggests.

read_to_string also gives a real example of "create a String in memory". It's funny the phrase "create a String in memory" was there since the very first commit....

...At first the phrase only described a hypothetical approach that would be less efficient ...

... then #1641 gave some actual code in a beginner-friendly method ... but it was no less efficient!...

...until #1679 or #1681 there was never actual code demonstrating the less efficient approach!

UPDATE #1679 was merged into master

huangapple
  • 本文由 发表于 2023年2月6日 17:37:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/75359557.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定