@@ -211,6 +211,115 @@ pub struct DirBuilder {
211211 recursive : bool ,
212212}
213213
214+ /// Read the entire contents of a file into a bytes vector.
215+ ///
216+ /// This is a convenience function for using [`File::open`] and [`read_to_end`]
217+ /// with fewer imports and without an intermediate variable.
218+ ///
219+ /// [`File::open`]: struct.File.html#method.open
220+ /// [`read_to_end`]: ../io/trait.Read.html#method.read_to_end
221+ ///
222+ /// # Errors
223+ ///
224+ /// This function will return an error if `path` does not already exist.
225+ /// Other errors may also be returned according to [`OpenOptions::open`].
226+ ///
227+ /// [`OpenOptions::open`]: struct.OpenOptions.html#method.open
228+ ///
229+ /// It will also return an error if it encounters while reading an error
230+ /// of a kind other than [`ErrorKind::Interrupted`].
231+ ///
232+ /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
233+ ///
234+ /// # Examples
235+ ///
236+ /// ```no_run
237+ /// #![feature(fs_read_write)]
238+ ///
239+ /// use std::fs;
240+ /// use std::net::SocketAddr;
241+ ///
242+ /// # fn foo() -> Result<(), Box<std::error::Error + 'static>> {
243+ /// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?;
244+ /// # Ok(())
245+ /// # }
246+ /// ```
247+ #[ unstable( feature = "fs_read_write" , issue = "46588" ) ]
248+ pub fn read < P : AsRef < Path > > ( path : P ) -> io:: Result < Vec < u8 > > {
249+ let mut bytes = Vec :: new ( ) ;
250+ File :: open ( path) ?. read_to_end ( & mut bytes) ?;
251+ Ok ( bytes)
252+ }
253+
254+ /// Read the entire contents of a file into a string.
255+ ///
256+ /// This is a convenience function for using [`File::open`] and [`read_to_string`]
257+ /// with fewer imports and without an intermediate variable.
258+ ///
259+ /// [`File::open`]: struct.File.html#method.open
260+ /// [`read_to_string`]: ../io/trait.Read.html#method.read_to_string
261+ ///
262+ /// # Errors
263+ ///
264+ /// This function will return an error if `path` does not already exist.
265+ /// Other errors may also be returned according to [`OpenOptions::open`].
266+ ///
267+ /// [`OpenOptions::open`]: struct.OpenOptions.html#method.open
268+ ///
269+ /// It will also return an error if it encounters while reading an error
270+ /// of a kind other than [`ErrorKind::Interrupted`],
271+ /// or if the contents of the file are not valid UTF-8.
272+ ///
273+ /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
274+ ///
275+ /// # Examples
276+ ///
277+ /// ```no_run
278+ /// #![feature(fs_read_write)]
279+ ///
280+ /// use std::fs;
281+ /// use std::net::SocketAddr;
282+ ///
283+ /// # fn foo() -> Result<(), Box<std::error::Error + 'static>> {
284+ /// let foo: SocketAddr = fs::read_string("address.txt")?.parse()?;
285+ /// # Ok(())
286+ /// # }
287+ /// ```
288+ #[ unstable( feature = "fs_read_write" , issue = "46588" ) ]
289+ pub fn read_string < P : AsRef < Path > > ( path : P ) -> io:: Result < String > {
290+ let mut string = String :: new ( ) ;
291+ File :: open ( path) ?. read_to_string ( & mut string) ?;
292+ Ok ( string)
293+ }
294+
295+ /// Write a slice as the entire contents of a file.
296+ ///
297+ /// This function will create a file if it does not exist,
298+ /// and will entirely replace its contents if it does.
299+ ///
300+ /// This is a convenience function for using [`File::create`] and [`write_all`]
301+ /// with fewer imports.
302+ ///
303+ /// [`File::create`]: struct.File.html#method.create
304+ /// [`write_all`]: ../io/trait.Write.html#method.write_all
305+ ///
306+ /// # Examples
307+ ///
308+ /// ```no_run
309+ /// #![feature(fs_read_write)]
310+ ///
311+ /// use std::fs;
312+ ///
313+ /// # fn foo() -> std::io::Result<()> {
314+ /// fs::write("foo.txt", b"Lorem ipsum")?;
315+ /// # Ok(())
316+ /// # }
317+ /// ```
318+ #[ unstable( feature = "fs_read_write" , issue = "46588" ) ]
319+ pub fn write < P : AsRef < Path > , C : AsRef < [ u8 ] > > ( path : P , contents : C ) -> io:: Result < ( ) > {
320+ File :: create ( path) ?. write_all ( contents. as_ref ( ) )
321+ }
322+
214323impl File {
215324 /// Attempts to open a file in read-only mode.
216325 ///
@@ -1912,7 +2021,9 @@ mod tests {
19122021 ) }
19132022
19142023 #[ cfg( unix) ]
1915- macro_rules! error { ( $e: expr, $s: expr) => (
2024+ macro_rules! error { ( $e: expr, $s: expr) => ( error_contains!( $e, $s) ) }
2025+
2026+ macro_rules! error_contains { ( $e: expr, $s: expr) => (
19162027 match $e {
19172028 Ok ( _) => panic!( "Unexpected success. Should've been: {:?}" , $s) ,
19182029 Err ( ref err) => assert!( err. to_string( ) . contains( $s) ,
@@ -2921,6 +3032,27 @@ mod tests {
29213032 assert ! ( v == & bytes[ ..] ) ;
29223033 }
29233034
3035+ #[ test]
3036+ fn write_then_read ( ) {
3037+ let mut bytes = [ 0 ; 1024 ] ;
3038+ StdRng :: new ( ) . unwrap ( ) . fill_bytes ( & mut bytes) ;
3039+
3040+ let tmpdir = tmpdir ( ) ;
3041+
3042+ check ! ( fs:: write( & tmpdir. join( "test" ) , & bytes[ ..] ) ) ;
3043+ let v = check ! ( fs:: read( & tmpdir. join( "test" ) ) ) ;
3044+ assert ! ( v == & bytes[ ..] ) ;
3045+
3046+ check ! ( fs:: write( & tmpdir. join( "not-utf8" ) , & [ 0xFF ] ) ) ;
3047+ error_contains ! ( fs:: read_string( & tmpdir. join( "not-utf8" ) ) ,
3048+ "stream did not contain valid UTF-8" ) ;
3049+
3050+ let s = "𐁁𐀓𐀠𐀴𐀍" ;
3051+ check ! ( fs:: write( & tmpdir. join( "utf8" ) , s. as_bytes( ) ) ) ;
3052+ let string = check ! ( fs:: read_string( & tmpdir. join( "utf8" ) ) ) ;
3053+ assert_eq ! ( string, s) ;
3054+ }
3055+
29243056 #[ test]
29253057 fn file_try_clone ( ) {
29263058 let tmpdir = tmpdir ( ) ;
0 commit comments