Shortest code to read and write a file


#1

Is that the shortest way to get a Vec<u8> contents of a file at run time?

fn main() {
    use std::io::Read;
    let mut c = Vec::new();
    std::fs::File::open("f").unwrap().read_to_end(&mut c).unwrap();
}

I’m asking, because I found myself writing these 3 lines in every program I write. Before I make myself a helper crate with one-stop function, I’d like to be sure I’m not reinventing something that’s already in stdlib.


#2

I make the same bug in every repl like program! :grinning:

let mut buffer = String::new();

loop {
    buffer.clear(); // <- always forget this ;(
    std::io::stdin().read_line(&mut buffer).unwrap();
    ...
}

#3

So I’ve created

https://crates.io/crates/file

extern crate file;
file::get("path");

That’s 2 lines instead of 3 :wink:


#4

Docs and repo links please?


#5

Added


#6

Great! You might want to:

  • Use io::Result<T> instead of Result<T, io::Error>
  • experiment with preallocating the buffer for reading (querying OS for the file size) because the standard implementation uses reallocation (and I’m not sure which approach is more efficient).

#7

It should go in standard library.


#8

See


#9

When I was doing tests on a 29MB file in Linux a few weeks ago, the preallocation approach was several times more efficient (~10ms versus ~40ms).

let metadata = try!(fs::metadata(&path));
let mut buf = Vec::with_capacity(metadata.len() as usize + 1);
// note: File's read_to_end uses the buffer capacity to choose how much to read
try!(fh.read_to_end(&mut buf));

Note, read_to_end detects EOF by trying to read into the part of the vector after the len and getting a zero byte result. This means that there will always be at least one byte of slack, and if you don’t preallocate a byte of slack there will be an unneeded reallocate at the very end.


#10

Surely it’s way faster on a large file. The question is how well it behaves on smaller files, because there the performance cost of an additional system call may not be negligible.


#11

Use read_exact() then