mirror of
https://github.com/rust-lang/rustlings.git
synced 2026-08-14 22:36:57 +00:00
Merge 4e9b5735ada47cc391b22a52ae12f6eb39c36fcc into 02b22b49e7349b36305dbe97cd5d6e198d2f0537
This commit is contained in:
commit
5aef50403a
@ -188,6 +188,12 @@ bin = [
|
|||||||
{ name = "conversions4_sol", path = "../solutions/23_conversions/conversions4.rs" },
|
{ name = "conversions4_sol", path = "../solutions/23_conversions/conversions4.rs" },
|
||||||
{ name = "conversions5", path = "../exercises/23_conversions/conversions5.rs" },
|
{ name = "conversions5", path = "../exercises/23_conversions/conversions5.rs" },
|
||||||
{ name = "conversions5_sol", path = "../solutions/23_conversions/conversions5.rs" },
|
{ name = "conversions5_sol", path = "../solutions/23_conversions/conversions5.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]
|
[package]
|
||||||
|
|||||||
30
exercises/24_file_io/README.md
Normal file
30
exercises/24_file_io/README.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# File IO
|
||||||
|
|
||||||
|
Rust provides several file I/O functions in the standard library. Buffered
|
||||||
|
reads and writes provide better performance by reducing the number of
|
||||||
|
underlying system calls.
|
||||||
|
|
||||||
|
## Learning goals
|
||||||
|
|
||||||
|
- **file_io1** — Read an entire file into memory with `fs::read_to_string`
|
||||||
|
and handle the `Result` it returns instead of unwrapping blindly, so you
|
||||||
|
get comfortable with the basic "open, read, handle the error" pattern
|
||||||
|
that most file I/O in Rust builds on.
|
||||||
|
- **file_io2** — Wrap a `File` in a `BufReader` to read it line by line and
|
||||||
|
a `BufWriter` to write the transformed output, so you understand why
|
||||||
|
buffering matters for I/O performance and how `BufRead::lines` lets you
|
||||||
|
process input incrementally instead of loading it all at once.
|
||||||
|
- **file_io3** — Build a path with `PathBuf`, then call `.metadata()` to
|
||||||
|
inspect properties like creation time, size, and permissions, so you can
|
||||||
|
work with the filesystem safely across platforms without hardcoding
|
||||||
|
path separators.
|
||||||
|
|
||||||
|
## Further information
|
||||||
|
|
||||||
|
Here is the documentation for these functions in the standard library.
|
||||||
|
|
||||||
|
- [read_to_string](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)
|
||||||
53
exercises/24_file_io/file_io1.rs
Normal file
53
exercises/24_file_io/file_io1.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
const TEST_FILE_NAME: &str = "SampleTextFile.txt";
|
||||||
|
const SAMPLE_TEXT: &str = "This is the file content.";
|
||||||
|
|
||||||
|
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, SAMPLE_TEXT)?;
|
||||||
|
} 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
exercises/24_file_io/file_io2.rs
Normal file
74
exercises/24_file_io/file_io2.rs
Normal file
@ -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";
|
||||||
|
const SAMPLE_TEXT: &str = "This is the first line of the text.
|
||||||
|
This is the second line.
|
||||||
|
And this is the third and the last line.";
|
||||||
|
|
||||||
|
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 lines_processed = 0;
|
||||||
|
|
||||||
|
for (index, line) in buffered_input_file.lines().enumerate() {
|
||||||
|
let line = line.inspect_err(|err| {
|
||||||
|
eprintln!("{} line parse error {:?}", TEST_INPUT_FILE_NAME, err);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let line_number = index + 1;
|
||||||
|
writeln!(buffered_file_writer, "Line {} : {}", line_number, line).inspect_err(|err| {
|
||||||
|
eprintln!("{} line write error {:?}", TEST_INPUT_FILE_NAME, err);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
lines_processed = line_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{} : lines processed", lines_processed);
|
||||||
|
file_cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_required_files() -> Result<(), std::io::Error> {
|
||||||
|
let file_path = Path::new(TEST_INPUT_FILE_NAME);
|
||||||
|
|
||||||
|
if !file_path.exists() {
|
||||||
|
fs::write(file_path, SAMPLE_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
exercises/24_file_io/file_io3.rs
Normal file
78
exercises/24_file_io/file_io3.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
use std::fs;
|
||||||
|
use std::io::Error;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
const SAMPLE_TEXT: &str = "This is the first line of the text.
|
||||||
|
This is the second line.
|
||||||
|
And this is the third and the last line.";
|
||||||
|
|
||||||
|
fn sample_file_path() -> PathBuf {
|
||||||
|
PathBuf::from("SampleFilesFolder/MultiLineTextFile.txt")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), std::io::Error> {
|
||||||
|
create_required_files()?;
|
||||||
|
|
||||||
|
let path_buffer = sample_file_path();
|
||||||
|
|
||||||
|
// 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(), SAMPLE_TEXT.len() as u64);
|
||||||
|
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 = sample_file_path();
|
||||||
|
|
||||||
|
let dir_path = file_path
|
||||||
|
.parent()
|
||||||
|
.ok_or_else(|| Error::other("Could not get parent path"))?;
|
||||||
|
|
||||||
|
if !dir_path.exists() {
|
||||||
|
fs::create_dir_all(dir_path).inspect_err(|x| {
|
||||||
|
eprintln!("Could not create directory: {:?}", x);
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !file_path.exists() {
|
||||||
|
fs::write(&file_path, SAMPLE_TEXT).inspect_err(|err| {
|
||||||
|
eprintln!("Couldn't create test file: {:?}", err);
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file_cleanup() -> Result<(), std::io::Error> {
|
||||||
|
let path_buffer = sample_file_path();
|
||||||
|
|
||||||
|
if path_buffer.exists() {
|
||||||
|
fs::remove_file(&path_buffer).inspect(|_| {
|
||||||
|
println!("Test file removed");
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(dir_path) = path_buffer.parent()
|
||||||
|
&& dir_path.exists()
|
||||||
|
{
|
||||||
|
fs::remove_dir(dir_path).inspect(|_| {
|
||||||
|
println!("Test dir removed");
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -304,7 +304,7 @@ Now, you have another tool in your toolbox!"""
|
|||||||
name = "vecs1"
|
name = "vecs1"
|
||||||
dir = "05_vecs"
|
dir = "05_vecs"
|
||||||
hint = """
|
hint = """
|
||||||
In Rust, there are two basic ways to define a Vector.
|
In Rust, there are two ways to define a Vector.
|
||||||
1. One way is to use the `Vec::new()` function to create a new vector
|
1. One way is to use the `Vec::new()` function to create a new vector
|
||||||
and fill it with the `push()` method.
|
and fill it with the `push()` method.
|
||||||
2. The second way is to use the `vec![]` macro and define your elements
|
2. The second way is to use the `vec![]` macro and define your elements
|
||||||
@ -1208,3 +1208,43 @@ name = "conversions5"
|
|||||||
dir = "23_conversions"
|
dir = "23_conversions"
|
||||||
hint = """
|
hint = """
|
||||||
Add `AsRef<str>` or `AsMut<u32>` as a trait bound to the functions."""
|
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 = """
|
||||||
|
Learning goal: read a whole file into memory and handle the Result it
|
||||||
|
produces, rather than unwrapping it.
|
||||||
|
|
||||||
|
`fs::read_to_string` returns a `Result<String, std::io::Error>`. Match on
|
||||||
|
it (or use `?`) to get the file's contents out of the `Ok` variant, and
|
||||||
|
compare that to the text that `create_required_files` wrote to the file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
[[exercises]]
|
||||||
|
name = "file_io2"
|
||||||
|
dir = "24_file_io"
|
||||||
|
test = false
|
||||||
|
hint = """
|
||||||
|
Learning goal: read a file efficiently, line by line, using a BufReader,
|
||||||
|
and understand why buffering matters for I/O performance.
|
||||||
|
|
||||||
|
`BufReader::new(input_file)` wraps a `File` so you can call `.lines()` on
|
||||||
|
it, which yields each line as a `Result<String, std::io::Error>`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
[[exercises]]
|
||||||
|
name = "file_io3"
|
||||||
|
dir = "24_file_io"
|
||||||
|
test = false
|
||||||
|
hint = """
|
||||||
|
Learning goal: build a filesystem path with PathBuf and inspect the file
|
||||||
|
it points to without hardcoding platform-specific path separators.
|
||||||
|
|
||||||
|
`Path`/`PathBuf` expose a `.metadata()` method that returns a
|
||||||
|
`Result<Metadata, std::io::Error>`, giving you access to creation time,
|
||||||
|
size (`.len()`), and permissions.
|
||||||
|
"""
|
||||||
|
|||||||
52
solutions/24_file_io/file_io1.rs
Normal file
52
solutions/24_file_io/file_io1.rs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
const TEST_FILE_NAME: &str = "SampleTextFile.txt";
|
||||||
|
const SAMPLE_TEXT: &str = "This is the file content.";
|
||||||
|
|
||||||
|
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!(SAMPLE_TEXT, 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, SAMPLE_TEXT)?;
|
||||||
|
} 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(())
|
||||||
|
}
|
||||||
73
solutions/24_file_io/file_io2.rs
Normal file
73
solutions/24_file_io/file_io2.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
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";
|
||||||
|
const SAMPLE_TEXT: &str = "This is the first line of the text.
|
||||||
|
This is the second line.
|
||||||
|
And this is the third and the last line.";
|
||||||
|
|
||||||
|
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 lines_processed = 0;
|
||||||
|
|
||||||
|
for (index, line) in buffered_input_file.lines().enumerate() {
|
||||||
|
let line = line.inspect_err(|err| {
|
||||||
|
eprintln!("{} line parse error {:?}", TEST_INPUT_FILE_NAME, err);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let line_number = index + 1;
|
||||||
|
writeln!(buffered_file_writer, "Line {} : {}", line_number, line).inspect_err(|err| {
|
||||||
|
eprintln!("{} line write error {:?}", TEST_INPUT_FILE_NAME, err);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
lines_processed = line_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{} : lines processed", lines_processed);
|
||||||
|
file_cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_required_files() -> Result<(), std::io::Error> {
|
||||||
|
let file_path = Path::new(TEST_INPUT_FILE_NAME);
|
||||||
|
|
||||||
|
if !file_path.exists() {
|
||||||
|
fs::write(file_path, SAMPLE_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(())
|
||||||
|
}
|
||||||
77
solutions/24_file_io/file_io3.rs
Normal file
77
solutions/24_file_io/file_io3.rs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
use std::fs;
|
||||||
|
use std::io::Error;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
const SAMPLE_TEXT: &str = "This is the first line of the text.
|
||||||
|
This is the second line.
|
||||||
|
And this is the third and the last line.";
|
||||||
|
|
||||||
|
fn sample_file_path() -> PathBuf {
|
||||||
|
PathBuf::from("SampleFilesFolder/MultiLineTextFile.txt")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), std::io::Error> {
|
||||||
|
create_required_files()?;
|
||||||
|
|
||||||
|
let path_buffer = sample_file_path();
|
||||||
|
|
||||||
|
let meta_data_result = path_buffer.metadata();
|
||||||
|
|
||||||
|
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(), SAMPLE_TEXT.len() as u64);
|
||||||
|
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 = sample_file_path();
|
||||||
|
|
||||||
|
let dir_path = file_path
|
||||||
|
.parent()
|
||||||
|
.ok_or_else(|| Error::other("Could not get parent path"))?;
|
||||||
|
|
||||||
|
if !dir_path.exists() {
|
||||||
|
fs::create_dir_all(dir_path).inspect_err(|x| {
|
||||||
|
eprintln!("Could not create directory: {:?}", x);
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !file_path.exists() {
|
||||||
|
fs::write(&file_path, SAMPLE_TEXT).inspect_err(|err| {
|
||||||
|
eprintln!("Couldn't create test file: {:?}", err);
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file_cleanup() -> Result<(), std::io::Error> {
|
||||||
|
let path_buffer = sample_file_path();
|
||||||
|
|
||||||
|
if path_buffer.exists() {
|
||||||
|
fs::remove_file(&path_buffer).inspect(|_| {
|
||||||
|
println!("Test file removed");
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(dir_path) = path_buffer.parent()
|
||||||
|
&& dir_path.exists()
|
||||||
|
{
|
||||||
|
fs::remove_dir(dir_path).inspect(|_| {
|
||||||
|
println!("Test dir removed");
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user