Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ bin = [
{ name = "try_from_into_sol", path = "../solutions/23_conversions/try_from_into.rs" },
{ name = "as_ref_mut", path = "../exercises/23_conversions/as_ref_mut.rs" },
{ name = "as_ref_mut_sol", path = "../solutions/23_conversions/as_ref_mut.rs" },
{ name = "file_io1", path = "../exercises/24_file_io/file_io1.rs" },
{ name = "file_io1_sol", path = "../solutions/24_file_io/file_io1.rs" },
{ name = "file_io2", path = "../exercises/24_file_io/file_io2.rs" },
{ name = "file_io2_sol", path = "../solutions/24_file_io/file_io2.rs" },
{ name = "file_io3", path = "../exercises/24_file_io/file_io3.rs" },
{ name = "file_io3_sol", path = "../solutions/24_file_io/file_io3.rs" },
]

[package]
Expand Down
16 changes: 16 additions & 0 deletions exercises/24_file_io/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# File IO

Rust Provides several file I/O functions in the standard library. Buffered reads and writes provides better performance by reducing underlying reads.

## Further information

Here is the documentation for these functions in the standard library.

- [ReadToString](https://doc.rust-lang.org/std/fs/fn.read_to_string.html)
- [BufReader](https://doc.rust-lang.org/std/io/struct.BufReader.html)
- [BufWriter](https://doc.rust-lang.org/std/io/struct.BufWriter.html)
- [Path](https://doc.rust-lang.org/stable/std/path/struct.Path.html)
- [PathBuf](https://doc.rust-lang.org/std/path/struct.PathBuf.html)



51 changes: 51 additions & 0 deletions exercises/24_file_io/file_io1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use std::fs;
use std::path::Path;

const TEST_FILE_NAME: &str = "SampleTextFile.txt";
fn main() -> Result<(), std::io::Error> {
create_required_files()?;

let read_str_result = fs::read_to_string(TEST_FILE_NAME);

match read_str_result {
Ok(contents) => {
// TODO : What would be the expected text ?
assert_eq!(, contents);
}
Err(err) => {
eprintln!("File read error. {}", err);
}
}

file_cleanup()?;
Ok(())
}

fn create_required_files() -> Result<(), std::io::Error> {
let file_path = Path::new(TEST_FILE_NAME);

if !file_path.exists() {
fs::write(file_path, "This is the file content.")?;
} else {
println!("File already exist.");
}

Ok(())
}

fn file_cleanup() -> Result<(), std::io::Error> {
let file_path = Path::new(TEST_FILE_NAME);

if file_path.exists() {
fs::remove_file(file_path).inspect(|_| {
println!("Test file {} deleted.", TEST_FILE_NAME);
})?;
} else {
println!(
"No cleanup necessary since {} not exist.",
file_path.display()
);
}

Ok(())
}
75 changes: 75 additions & 0 deletions exercises/24_file_io/file_io2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use std::fs;
use std::io::{BufRead, BufReader, BufWriter, Write};
use std::path::Path;

const TEST_INPUT_FILE_NAME: &str = "MultiLineTextFile.txt";
const TEST_OUTPUT_FILE_NAME: &str = "MultiLineOutputFile.txt";

fn main() -> Result<(), std::io::Error> {
create_required_files()?;

let input_file = fs::File::open(TEST_INPUT_FILE_NAME).inspect_err(|err| {
eprintln!("{} file open error {:?}", TEST_INPUT_FILE_NAME, err);
})?;

// TODO : How to create a new BufReader using input file
let buffered_input_file =;

let output_file = fs::File::create(TEST_OUTPUT_FILE_NAME).inspect_err(|err| {
eprintln!("{} file open error {:?}", TEST_OUTPUT_FILE_NAME, err);
})?;

let mut buffered_file_writer = BufWriter::new(output_file);

let mut line_number = 1;

for line in buffered_input_file.lines() {
let line = line.inspect_err(|err| {
eprintln!("{} line parse error {:?}", TEST_INPUT_FILE_NAME, err);
})?;

buffered_file_writer
.write(format!("Line {} : {}\n", line_number, line).as_bytes())
.inspect_err(|err| {
eprintln!("{} line write error {:?}", TEST_INPUT_FILE_NAME, err);
})?;

line_number += 1;
}

println!("{} : lines processed", line_number - 1);
file_cleanup()
}

fn create_required_files() -> Result<(), std::io::Error> {
let file_path = Path::new(TEST_INPUT_FILE_NAME);

if !file_path.exists() {
let text = "This is the first line of the text.
This is the second line.
And this is the third and the last line.";
fs::write(file_path, text).inspect_err(|err| {
eprintln!("Couldn't create the test file : {}", err);
})?;
}

Ok(())
}

fn file_cleanup() -> Result<(), std::io::Error> {
let file_names = vec![TEST_INPUT_FILE_NAME, TEST_OUTPUT_FILE_NAME];

for file_name in file_names {
let file_path = Path::new(file_name);

if file_path.exists() {
fs::remove_file(file_path).inspect(|_| {
println!("Test file {} removed", file_name);
})?;
} else {
println!("No cleanup necessary since {} not exist.", file_name);
}
}

Ok(())
}
78 changes: 78 additions & 0 deletions exercises/24_file_io/file_io3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use std::fs;
use std::io::Error;
use std::path::PathBuf;

fn main() -> Result<(), std::io::Error> {
create_required_files()?;
let mut path_buffer = PathBuf::new();

path_buffer.push("SampleFilesFolder");
path_buffer.push("MultiLineTextFile.txt");

// TODO : How to get metadata using path_buffer ?
let meta_data_result = path_buffer.

match meta_data_result {
Ok(meta_data) => {
println!("Metadata about the file : {:?}", path_buffer);
println!("File creation time {:?}", meta_data.created());
println!("File size {}", meta_data.len());
assert_eq!(meta_data.len(), 117);
println!("File permissions {:?}", meta_data.permissions());
assert!(!meta_data.permissions().readonly());
}
Err(error) => {
eprintln!("Could not get metadata. Error: {:?}", error);
}
}

file_cleanup()
}

fn create_required_files() -> Result<(), std::io::Error> {
let file_path = PathBuf::from("SampleFilesFolder/MultiLineTextFile.txt");

let dir_path = match file_path.parent(){
Some(parent) => parent,
None => return Err(Error::other("Could not get parent path")),
};

if !dir_path.exists() {
fs::create_dir(dir_path).inspect_err(|x| {
eprintln!("Could not create directory: {:?}", x);
})?;
}

if !file_path.exists() {
let text = "This is the first line of the text.
This is the second line.
And this is the third and the last line.";
fs::write(&file_path, text).inspect_err(|err| {
eprintln!("Couldn't create test file: {:?}", err);
})?;
}

Ok(())
}

fn file_cleanup() -> Result<(), std::io::Error> {
let mut path_buffer = PathBuf::new();

path_buffer.push("SampleFilesFolder");
path_buffer.push("MultiLineTextFile.txt");

if path_buffer.exists() {
fs::remove_file(&path_buffer).inspect(|_| {
println!("Test file removed");
})?;
}
path_buffer.pop();

if path_buffer.exists() {
fs::remove_dir(&path_buffer).inspect(|_| {
println!("Test dir removed");
})?;
}

Ok(())
}
26 changes: 26 additions & 0 deletions rustlings-macros/info.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1200,3 +1200,29 @@ name = "as_ref_mut"
dir = "23_conversions"
hint = """
Add `AsRef<str>` or `AsMut<u32>` as a trait bound to the functions."""

# File IO Exercises

[[exercises]]
name = "file_io1"
dir = "24_file_io"
test = false
hint = """
Basic File Reading
"""

[[exercises]]
name = "file_io2"
dir = "24_file_io"
test = false
hint = """
Buffered Reading & Writing
"""

[[exercises]]
name = "file_io3"
dir = "24_file_io"
test = false
hint = """
Path Manipulation & Metadata
"""
50 changes: 50 additions & 0 deletions solutions/24_file_io/file_io1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use std::fs;
use std::path::Path;

const TEST_FILE_NAME: &str = "SampleTextFile.txt";
fn main() -> Result<(), std::io::Error> {
create_required_files()?;

let read_str_result = fs::read_to_string(TEST_FILE_NAME);

match read_str_result {
Ok(contents) => {
assert_eq!("This is the file content.", contents);
}
Err(err) => {
eprintln!("File read error. {}", err);
}
}

file_cleanup()?;
Ok(())
}

fn create_required_files() -> Result<(), std::io::Error> {
let file_path = Path::new(TEST_FILE_NAME);

if !file_path.exists() {
fs::write(file_path, "This is the file content.")?;
} else {
println!("File already exist.");
}

Ok(())
}

fn file_cleanup() -> Result<(), std::io::Error> {
let file_path = Path::new(TEST_FILE_NAME);

if file_path.exists() {
fs::remove_file(file_path).inspect(|_| {
println!("Test file {} deleted.", TEST_FILE_NAME);
})?;
} else {
println!(
"No cleanup necessary since {} not exist.",
file_path.display()
);
}

Ok(())
}
74 changes: 74 additions & 0 deletions solutions/24_file_io/file_io2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use std::fs;
use std::io::{BufRead, BufReader, BufWriter, Write};
use std::path::Path;

const TEST_INPUT_FILE_NAME: &str = "MultiLineTextFile.txt";
const TEST_OUTPUT_FILE_NAME: &str = "MultiLineOutputFile.txt";

fn main() -> Result<(), std::io::Error> {
create_required_files()?;

let input_file = fs::File::open(TEST_INPUT_FILE_NAME).inspect_err(|err| {
eprintln!("{} file open error {:?}", TEST_INPUT_FILE_NAME, err);
})?;

let buffered_input_file = BufReader::new(input_file);

let output_file = fs::File::create(TEST_OUTPUT_FILE_NAME).inspect_err(|err| {
eprintln!("{} file open error {:?}", TEST_OUTPUT_FILE_NAME, err);
})?;

let mut buffered_file_writer = BufWriter::new(output_file);

let mut line_number = 1;

for line in buffered_input_file.lines() {
let line = line.inspect_err(|err| {
eprintln!("{} line parse error {:?}", TEST_INPUT_FILE_NAME, err);
})?;

buffered_file_writer
.write(format!("Line {} : {}\n", line_number, line).as_bytes())
.inspect_err(|err| {
eprintln!("{} line write error {:?}", TEST_INPUT_FILE_NAME, err);
})?;

line_number += 1;
}

println!("{} : lines processed", line_number - 1);
file_cleanup()
}

fn create_required_files() -> Result<(), std::io::Error> {
let file_path = Path::new(TEST_INPUT_FILE_NAME);

if !file_path.exists() {
let text = "This is the first line of the text.
This is the second line.
And this is the third and the last line.";
fs::write(file_path, text).inspect_err(|err| {
eprintln!("Couldn't create the test file : {}", err);
})?;
}

Ok(())
}

fn file_cleanup() -> Result<(), std::io::Error> {
let file_names = vec![TEST_INPUT_FILE_NAME, TEST_OUTPUT_FILE_NAME];

for file_name in file_names {
let file_path = Path::new(file_name);

if file_path.exists() {
fs::remove_file(file_path).inspect(|_| {
println!("Test file {} removed", file_name);
})?;
} else {
println!("No cleanup necessary since {} not exist.", file_name);
}
}

Ok(())
}
Loading