Unable to read file contents to string - Result does not implement any method in scope named `read_to_string`

I followed the code to open a file from Rust by Example:

use std::{env, fs::File, path::Path};

fn main() {
    let args: Vec<_> = env::args().collect();
    let pattern = &args[1];

    if let Some(a) = env::args().nth(2) {
        let path = Path::new(&a);
        let mut file = File::open(&path);
        let mut s = String::new();
        file.read_to_string(&mut s);
        println!("{:?}", s);
    } else {
        //do something
    }
}

However, I got a message like this:

error[E0599]: no method named `read_to_string` found for type `std::result::Result<std::fs::File, std::io::Error>` in the current scope
  --> src/main.rs:11:14
   |
11 |         file.read_to_string(&mut s);
   |              ^^^^^^^^^^^^^^ method not found in `std::result::Result<std::fs::File, std::io::Error>`

What am I doing wrong?


Solution 1:

Let's look at your error message:

error[E0599]: no method named `read_to_string` found for type `std::result::Result<std::fs::File, std::io::Error>` in the current scope
  --> src/main.rs:11:14
   |
11 |         file.read_to_string(&mut s);
   |              ^^^^^^^^^^^^^^ method not found in `std::result::Result<std::fs::File, std::io::Error>`

The error message is pretty much what it says on the tin - the type Result does not have the method read_to_string. That's actually a method on the trait Read.

You have a Result because File::open(&path) can fail. Failure is represented with the Result type. A Result may be either an Ok, which is the success case, or an Err, the failure case.

You need to handle the failure case somehow. The easiest is to just die on failure, using expect:

let mut file = File::open(&path).expect("Unable to open");

You'll also need to bring Read into scope to have access to read_to_string:

use std::io::Read;

I'd highly recommend reading through The Rust Programming Language and working the examples. The chapter Recoverable Errors with Result will be highly relevant. I think these docs are top-notch!

Solution 2:

If your method returns Result<String, io::Error>, you can use ? on the functions that return a Result:

fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = File::open("hello.txt")?;
    let mut s = String::new();
    f.read_to_string(&mut s)?;
    Ok(s)
}

If you cannot return a Result<String, io::Error> then you have to handle error case using expect as mentioned in the accepted answer or matching on the Result and panicking:

let file = File::open(&opt_raw.config);

let file = match file {
    Ok(file) => file,
    Err(error) => {
        panic!("Problem opening the file: {:?}", error)
    }
};                                                                  

For more information, please refer to Recoverable Errors with Result.