@@ -211,6 +211,115 @@ pub struct DirBuilder {
211
211
recursive : bool ,
212
212
}
213
213
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
+
214
323
impl File {
215
324
/// Attempts to open a file in read-only mode.
216
325
///
@@ -1912,7 +2021,9 @@ mod tests {
1912
2021
) }
1913
2022
1914
2023
#[ 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) => (
1916
2027
match $e {
1917
2028
Ok ( _) => panic!( "Unexpected success. Should've been: {:?}" , $s) ,
1918
2029
Err ( ref err) => assert!( err. to_string( ) . contains( $s) ,
@@ -2921,6 +3032,27 @@ mod tests {
2921
3032
assert ! ( v == & bytes[ ..] ) ;
2922
3033
}
2923
3034
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
+
2924
3056
#[ test]
2925
3057
fn file_try_clone ( ) {
2926
3058
let tmpdir = tmpdir ( ) ;
0 commit comments