1

I would like to read a specific line of a file, if the:

  • file does not exist
  • file cannot be open
  • the number of lines is less that the one that I want

just return an empty string.

Consider the following examples:

let wifi = "".to_string();
if let Ok(wifi_file) = fs::read_to_string("/proc/net/wireless") {
    if let Some(wifi_level) = wifi_file.lines().nth(2) {
        let wifi = format!("{:.0} dBa ", wifi_level
            .split_whitespace()
            .collect::<Vec<&str>>()[3]
            .parse::<f32>()
            .unwrap()
        );
    }
}
// wifi is out of scope
let wifi = match fs::read_to_string("/proc/net/wireless") {
    Ok(s) => format!("{:.0} dBA", s.lines()
        .nth(2)
        .expect("Unable to open")
        .split_whitespace()
        .collect::<Vec<&str>>()[3]
        .parse::<f32>()
        .unwrap()),
    Err(_) => "".to_string(),
};
// thread 'main' panicked at 'Unable to open', ...

Am I missing something obvious about match?

2 Answers 2

2

In your first code, you are declaring wifi variable again instead of using the already declared variable.

Working code:

let mut wifi = "".to_string();
if let Ok(wifi_file) = fs::read_to_string("/proc/net/wireless") {
    if let Some(wifi_level) = wifi_file.lines().nth(2) {
        wifi = format!("{:.0} dBa ", wifi_level
            .split_whitespace()
            .collect::<Vec<&str>>()[3]
            .parse::<f32>()
            .unwrap()
        );
    }
}

Second code is working without any changes.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your reply. The second code crashes when the file contains only 2 lines instead of 3.
@yellowhat actually it crashes if the third line doesn't contain a valid f32. To handle this case don't call unwrap, but use another if let Ok (float_level) = … instead.
For my understanding: does the match(Ok / Err) just covers fs::read_to_string("/proc/net/wireless") not s.lines().nth(2).expect("Unable to open") ...?
@yellowhat Rust doesn't have exceptions like C++/Java/Python that can break the control flow. In Rust, match is just the same as switch … case in those languages. OTOH, expect (like unwrap) means: "crash if the expectation is not met" (e.g. if the value is Err for a Result or None for an Option).
1

You already have an answer, but this code can be simplified if you encapsulate it in a function returning an Option and use ? for none-propagation:

fn get_wifi(path: &str, n: usize) -> Option<String> {
    let file = std::fs::read_to_string(path).ok()?;
    let level = file.lines().nth(n)?;
    let value = level.split_whitespace().nth(3)?.parse::<f32>().ok()?;
    
    Some(format!("{:.0} dBa ", value))
}

You can then call it like this:

let wifi = get_wifi("/proc/net/wireless", 2).unwrap_or_default();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.