file/
lib.rs

1//! # File I/O 1-liners
2//!
3//! `file::get()` and `file::put()` — read and write `Vec<u8>` with one function call.
4//!
5//! ```rust
6//! extern crate file;
7//!
8//! fn example() -> file::Result<()> {
9//!     let data = file::get("some_input_file.dat")?;
10//!     file::put("a.out", &data)?;
11//!     Ok(())
12//! }
13//! ```
14//!
15//! `file::Result` is an alias for `std::io::Result`. You can use `Result<(), Box<std::error::Error>>` in places where you don't want to expose the error type.
16//!
17//! ## Text file 1-liners
18//!
19//! `file::get_text()` and `file::put_text()` — read and write `String` with one function call.
20//!
21//! ```rust
22//! extern crate file;
23//!
24//! fn example() -> file::Result<()> {
25//!     let string = file::get_text("hello.txt")?;
26//!     file::put("bye.txt", &string)?;
27//!     Ok(())
28//! }
29//! ```
30
31use std::fs::File;
32use std::path::Path;
33use std::io;
34use std::io::{Read, Write};
35
36pub use io::Result;
37
38/// Read a file into `Vec<u8>` from the given path.
39/// The path can be a string or a `Path`.
40pub fn get<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
41    let mut file = File::open(path)?;
42    let mut data = Vec::new();
43    if let Ok(meta) = file.metadata() {
44        data.reserve(meta.len() as usize); // Safe to truncate, since it's only a suggestion
45    }
46    file.read_to_end(&mut data)?;
47    Ok(data)
48}
49
50/// Creates a file at the given path with contents of `Vec<u8>` or `&[u8]`, etc.
51/// Overwrites, non-atomically, if the file exists.
52/// The path can be a string or a `Path`.
53pub fn put<P: AsRef<Path>, Bytes: AsRef<[u8]>>(path: P, data: Bytes) -> io::Result<()> {
54    let mut file = File::create(path)?;
55    file.write_all(data.as_ref())?;
56    Ok(())
57}
58
59/// Read an UTF-8 encoded file into `String` from the given path.
60/// The path can be a string or a `Path`.
61pub fn get_text<P: AsRef<Path>>(path: P) -> io::Result<String> {
62    let bytes = get(path)?;
63    String::from_utf8(bytes).map_err(|_| {
64        io::Error::new(io::ErrorKind::InvalidData, "file did not contain valid UTF-8")
65    })
66}
67
68/// Creates a file at the given path with given text contents, encoded as UTF-8.
69/// Overwrites, non-atomically, if the file exists.
70/// The path can be a string or a `Path`.
71pub fn put_text<P: AsRef<Path>, S: AsRef<str>>(path: P, data: S) -> io::Result<()> {
72    put(path, data.as_ref().as_bytes())
73}
74
75
76#[test]
77fn it_works() {
78    let s = String::from_utf8(get(file!()).unwrap()).unwrap();
79    assert!(s.contains("it_works()"));
80
81    let mut tmp_name = std::env::temp_dir();
82    tmp_name.push("tmp_file_should_not_exist");
83
84    assert!(get(tmp_name).is_err());
85
86    let mut tmp_name = std::env::temp_dir();
87    tmp_name.push("tmp_file_created");
88
89    let data = vec![0u8,1,2,3];
90    put(&tmp_name, &data).unwrap();
91    assert_eq!(data, get(&tmp_name).unwrap());
92    put(&tmp_name, data).unwrap();
93
94    std::fs::remove_file(tmp_name).ok();
95}
96
97#[test]
98fn it_works_with_text() {
99    let s = String::from_utf8(get(file!()).unwrap()).unwrap();
100    assert!(s.contains("it_works()"));
101
102    let mut tmp_name = std::env::temp_dir();
103    tmp_name.push("hello");
104
105    put(&tmp_name, [0x80]).unwrap();
106    if let Err(e) = get_text(&tmp_name) {
107        assert_eq!(e.kind(), io::ErrorKind::InvalidData);
108    } else {
109        panic!("Should error on invalid UTF-8")
110    }
111
112    let text = "Hello, World!";
113    put_text(&tmp_name, text).unwrap();
114    assert_eq!(text, get_text(&tmp_name).unwrap());
115
116    std::fs::remove_file(tmp_name).ok();
117}