None of this has anything to do with ?
or Result
or what the function returns, really.
@alice is correct in saying that your problem seems to be that you don't specify how you want to handle the error, which makes us miss the point, the broader picture.
There is another, distinct problem: the "infinite" error handling you are running into is the consequence of how you think about the problem. Assuming you do indeed want to ask the user for another file name, you formulate the problem as:
- Try to open file
- If it fails, ask user for new filename
- Try to open new file
- If it fails, ask user for yet another filename
- Try to open 3rd file as well
- If it fails, ask for new filename again… etc.
Of course, you don't want to write code for this, it would indeed result in an infinitely-long piece of code, nested infinitely deeply as well. But you don't need that. You are doing the same thing over and over again. Doesn't that sound suspicious? What you need is a plain old loop:
use std::fs::File;
use std::io::{ stdin, stdout, Read, BufRead, Write };
fn main() {
// get access to stdin and stdout
let input = stdin();
let mut input = input.lock();
let output = stdout();
let mut output = output.lock();
// ask for file name until it is valid
let mut file = loop {
print!("Enter file name: ");
output.flush().unwrap();
let mut filename = String::new();
input.read_line(&mut filename).unwrap();
// trim trailing '\n' so that the file name is valid
match File::open(filename.trim()) {
Ok(file) => break file, // exit the loop with the opened file
Err(_) => {} // do nothing, i.e. keep going
}
};
// read contents of file and print it to stdout
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
println!("Contents:\n---------{}", contents);
}