13

As my first dive into Rust in a while, I started writing code to dump the contents of a file to a string, for later processing (right now I'm just printing it out though)

Is there a cleaner way to do this than I currently am? It seems like I'm having to be way too verbose about it, but I'm not seeing any good way to clean it up

use std::io;
use std::io::File;
use std::os;
use std::str;

fn main() {
    println!("meh");
    let filename = &os::args()[1];
    let contents = match File::open(&Path::new(filename)).read_to_end() {
        Ok(s) => str::from_utf8(s.as_slice()).expect("this shouldn't happen").to_string(),
        Err(e) => "".to_string(),
    };
    println!("ugh {}", contents.to_string());
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Earlz
  • 62,085
  • 98
  • 303
  • 499

1 Answers1

23

Editor's note: review the linked duplicate for a maintained answer with shorter / cleaner answers.

Read::read_to_string is the shortest I know of:

use std::io::prelude::*;
use std::fs::File;

fn main() {
    let mut file = File::open("/etc/hosts").expect("Unable to open the file");
    let mut contents = String::new();
    file.read_to_string(&mut contents).expect("Unable to read the file");
    println!("{}", contents);
}

Having to think about failure cases is something that Rust likes to place front and center.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • You should not use `unwrap` in production code. Either `match`, `map` or `and_then`. – Hauleth May 23 '15 at 17:39
  • 4
    @hauleth That's a very strict pronouncement. Are you making the same claim for `panic`, `unreachable`, or `assert`? All of these generate a thread panic. There's plenty of reasons to `panic` in production code. Specifically, I'd state that coding **logic errors** *should* cause a panic when they are encountered. Of course, this example isn't production code, and handling error cases is up to the user of the example and the context of that application. – Shepmaster May 23 '15 at 18:26
  • 1
    IMHO yes. You should avoid all of them if you can. Personally I use them only if I'm certain that this won't panic (i. e. `FromPrimitive` on constants). If I need to panic then it should happen in `main`. In libraries you should return `Result` or `Option`, or use `log` crate if it isn't fatal. – Hauleth May 23 '15 at 18:40
  • 1
    @Hauleth If the error isn't recoverable, it's oftentimes more useful to abort right when you receive it and get a stack trace rather than pass the error all the way up to `main` and thereby lose all context about the error. `panic` and `expect` have their uses. – Ponkadoodle Apr 18 '18 at 03:12
  • 1
    I do wish there was a `fn read_as_string() -> Result` for when we don't already have a buffer. Would be more ergonomic in many places. – Ponkadoodle Apr 18 '18 at 03:16
  • @Ponkadoodle read the linked duplicate. There is such a function in the next version of Rust. – Shepmaster Apr 18 '18 at 03:17
  • Exactly the code snippet I needed! +1 – Jman Jul 07 '19 at 23:06