1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! # file_into_string Rust crate
//! 
//! Read a typical text file into a string or vector of strings.
//! 
//! * `file_into_string(file: File) -> std::io::Result<String>`
//! 
//! * `file_into_strings(file: File) -> std::io::Result<Vec<String>>`
//! 
//! Examples:
//! 
//! ```rust
//! use std::fs::File;
//! use file_into_string::*;
//! 
//! // Open an existing text file; read the File into a String.
//! let file = File::open("example.txt").unwrap();
//! let string = file_into_string(file).unwrap();
//! 
//! // Open an existing text file; read the File into a Vec<String>.
//! let file = File::open("example.txt").unwrap();
//! let strings = file_into_strings(file).unwrap();
//! ```
//! 
//! ## Install
//! 
//! You can use this Rust crate:
//! 
//! ```toml
//! [dependencies]
//! file_into_string = "*"
//! ```
//! 
//! Or if you prefer, you can copy the source code into your own program.
//! 
//! ## Notes
//! 
//! These functions deliberately preserve line endings,
//! which are `\n` newlines and `\r` carriage returns.
//! 
//! These functions use buffered readers for efficiency.
//! 
//! These functions are written to be easy to understand,
//! so you can copy them into your own code if you wish.
//! 
//! If you're reading very large files, then you may prefer
//! to write your own code to process each line as it's read.
//! 
//! ## Tracking
//! 
//! * Project: file-into-string-rust-crate
//! * Version: 1.1.0
//! * Created: 2022-10-01T22:58:34Z
//! * Updated: 2022-10-12T21:56:45Z
//! * Website: https://github.com/sixarm/file-into-string-rust-crate
//! * Contact: Joel Parker Henderson <joel@joelparkerhenderson.com>
//! * License: MIT OR Apache-2.0 OR GPL-2.0 OR GPL-3.0
  
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;

/// Read a File into a String.
/// 
/// ```
/// use std::fs::File;
/// use file_into_string::*;
/// 
/// let file: File = File::open("example.txt").unwrap();
/// let string: String = file_into_string(file).unwrap();
/// ```
/// 
/// Note: this function deliberately preserves line endings,
/// which are `\n` newlines and `\r` carriage returns.
/// 
pub fn file_into_string(file: File) -> ::std::io::Result<String> {
    let mut string = String::new();
    let mut reader = BufReader::new(file);
    let mut buf = String::new();
    let mut n: usize;
    loop {
        n = reader.read_line(&mut buf)?;
        if n == 0 { break; }
        string.push_str(&buf);
        buf.clear();
    }
    Ok(string)
}

/// Read a File into a Vec<String>.
/// 
/// ```
/// use std::fs::File;
/// use file_into_string::*;
/// 
/// let file: File = File::open("example.txt").unwrap();
/// let strings: Vec<String> = file_into_strings(file).unwrap();
/// ```
/// 
/// Note: this function deliberately preserves line endings,
/// which are `\n` newlines and `\r` carriage returns.
/// 
pub fn file_into_strings(file: File) -> ::std::io::Result<Vec<String>> {
    let mut strings = Vec::<String>::new();
    let mut reader = BufReader::new(file);
    let mut buf = String::new();
    let mut n: usize;
    loop {
        n = reader.read_line(&mut buf)?;
        if n == 0 { break; }
        strings.push(buf.clone());
        buf.clear();
    }
    Ok(strings)
}

#[cfg(test)]
mod tests {
    use super::*;

    static PATH: &str = "example.txt"; // The contents must be "lorem\nipsum\n"

    #[test]
    fn test_file_into_string() {
        let file = std::fs::File::open(PATH).unwrap();
        let s = file_into_string(file).unwrap();
        assert_eq!(s, "lorem\nipsum\n");
    }

    #[test]
    fn test_file_into_strings() {
        let file = std::fs::File::open(PATH).unwrap();
        let actual_strings = file_into_strings(file).unwrap();
        let expect_strings = vec![String::from("lorem\n"), String::from("ipsum\n")];
        assert_eq!(actual_strings, expect_strings);
    }

}