From fd518ac4b0fe30b13d2fdf0f1b4b9fa129d75dff Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 7 Nov 2017 16:17:03 +0100 Subject: [PATCH] Add File::read_contents and File::write_contents convenience functions. Before: ```rust use std::fs::File; use std::io::Read; let mut bytes = Vec::new(); File::open(filename)?.read_to_end(&mut bytes)?; do_something_with(bytes) ``` After: ```rust use std::fs::File; do_something_with(File::read_contents(filename)?) ``` --- src/libstd/fs.rs | 79 +++++++++++++++++++++++++++++++++++++++++++++++ src/libstd/lib.rs | 1 + 2 files changed, 80 insertions(+) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index b07733d3c80..9b41cde30fb 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -262,6 +262,73 @@ impl File { OpenOptions::new().write(true).create(true).truncate(true).open(path.as_ref()) } + /// Read the entire contents of a file into a bytes vector. + /// + /// This is a convenience function for using [`File::open`] and [`read_to_end`] + /// with fewer imports and without an intermediate variable. + /// + /// [`File::open`]: struct.File.html#method.open + /// [`read_to_end`]: ../io/trait.Read.html#method.read_to_end + /// + /// # Errors + /// + /// This function will return an error if `path` does not already exist. + /// Other errors may also be returned according to [`OpenOptions::open`]. + /// + /// [`OpenOptions::open`]: struct.OpenOptions.html#method.open + /// + /// It will also return an error if it encounters while reading an error + /// of a kind other than [`ErrorKind::Interrupted`]. + /// + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// + /// # Examples + /// + /// ```no_run + /// #![feature(file_read_write_contents)] + /// + /// use std::fs::File; + /// + /// # fn foo() -> Result<(), Box> { + /// let foo = String::from_utf8(File::read_contents("foo.txt")?)?; + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "file_read_write_contents", issue = /* FIXME */ "0")] + pub fn read_contents>(path: P) -> io::Result> { + let mut bytes = Vec::new(); + File::open(path)?.read_to_end(&mut bytes)?; + Ok(bytes) + } + + /// Write the give contents to a file. + /// + /// This function will create a file if it does not exist, + /// and will entirely replace its contents if it does. + /// + /// This is a convenience function for using [`File::create`] and [`write_all`] + /// with fewer imports. + /// + /// [`File::create`]: struct.File.html#method.create + /// [`write_all`]: ../io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// ```no_run + /// #![feature(file_read_write_contents)] + /// + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// File::write_contents("foo.txt", b"Lorem ipsum")?; + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "file_read_write_contents", issue = /* FIXME */ "0")] + pub fn write_contents>(path: P, contents: &[u8]) -> io::Result<()> { + File::create(path)?.write_all(contents) + } + /// Attempts to sync all OS-internal metadata to disk. /// /// This function will attempt to ensure that all in-core data reaches the @@ -2921,6 +2988,18 @@ mod tests { assert!(v == &bytes[..]); } + #[test] + fn write_contents_then_read_contents() { + let mut bytes = [0; 1024]; + StdRng::new().unwrap().fill_bytes(&mut bytes); + + let tmpdir = tmpdir(); + + check!(File::write_contents(&tmpdir.join("test"), &bytes)); + let v = check!(File::read_contents(&tmpdir.join("test"))); + assert!(v == &bytes[..]); + } + #[test] fn file_try_clone() { let tmpdir = tmpdir(); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 429153dc58b..698830cc45b 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -269,6 +269,7 @@ #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] +#![feature(file_read_write_contents)] #![feature(fixed_size_array)] #![feature(float_from_str_radix)] #![feature(fn_traits)]