Back to the basics - Reading and writing files
Spoiler
main.rs
use crate::utils::{read_people, write_people, Person};
mod utils;
fn main() {
let person = Person::new();
let people = vec![person];
match write_people(people) {
Ok(_) => println!("people.txt was written successfully"),
Err(err) => println!("There was error while writing people.txt: {}", err),
}
match read_people() {
Ok(_people) => println!("people.txt was read successfully"),
Err(err) => println!("There was error while reading people.txt: {}", err),
}
}
utils.rs
use std::fs::{read_to_string, write};
use std::str::{FromStr, Split};
pub struct Person {
pub first_name: String,
pub last_name: String,
pub age: u8,
}
impl Person {
pub fn new() -> Self {
let first_name = ask_for_a_string("What is your first name?");
let last_name = ask_for_a_string("What is your last name?");
let age = ask_for_a_number("How old are you?").unwrap_or(0);
Person {
first_name,
last_name,
age,
}
}
}
pub fn read_string() -> String {
let mut input = String::new();
std::io::stdin()
.read_line(&mut input)
.expect("can not read user input");
input.trim().to_string()
}
pub fn read_number() -> Result<u8, String> {
let input = read_string();
if input.is_empty() {
Err("You did not enter any data".to_string())
} else {
u8::from_str(&input).or(Err("You've entered an invalid number".to_string()))
}
}
fn ask(question: &str) {
println!("{}", question);
}
pub fn ask_for_a_string(question: &str) -> String {
ask(question);
read_string()
}
pub fn ask_for_a_number(question: &str) -> Result<u8, String> {
ask(question);
read_number()
}
pub fn write_people(people: Vec<Person>) -> std::io::Result<()> {
let mut output = String::new();
for person in people {
output.push_str(&person.first_name);
output.push('\n');
output.push_str(&person.last_name);
output.push('\n');
output.push_str(&person.age.to_string());
output.push('\n');
}
write("people.txt", output)
}
fn read_person(lines: &mut Split<char>) -> Option<Person> {
let first_name = lines.next()?;
let last_name = lines.next()?;
let age_as_string = lines.next()?;
let age = u8::from_str(&age_as_string).unwrap_or(0);
let person = Person {
first_name: first_name.to_string(),
last_name: last_name.to_string(),
age,
};
Some(person)
}
pub fn read_people() -> Result<Vec<Person>, std::io::Error> {
let input = read_to_string("people.txt")?;
let mut lines = input.split('\n');
let mut people = vec![];
while let Some(person) = read_person(&mut lines) {
people.push(person)
}
Ok(people)
}