Read & Write

Read lines of strings from a file

std-badge cat-filesystem-badge

Writes a three-line message to a file, then reads it back a line at a time with the Lines iterator created by BufRead::lines. File implements Read which provides BufReader trait. File::create opens a File for writing, File::open for reading.

# #[macro_use]
# extern crate error_chain;
#
use std::fs::File;
use std::io::{Write, BufReader, BufRead};
#
# error_chain! {
#     foreign_links {
#         Io(std::io::Error);
#     }
# }

fn run() -> Result<()> {
    let path = "lines.txt";

    let mut output = File::create(path)?;
    write!(output, "Rust\nšŸ’–\nFun")?;

    let input = File::open(path)?;
    let buffered = BufReader::new(input);

    for line in buffered.lines() {
        println!("{}", line?);
    }

    Ok(())
}
#
# quick_main!(run);

Avoid writing and reading from a same file

same_file-badge cat-filesystem-badge

Use same_file::Handle to a file that can be tested for equality with other handles. In this example, the handles of file to be read from and to be written to are tested for equality.

# #[macro_use]
# extern crate error_chain;
extern crate same_file;

use same_file::Handle;
use std::path::Path;
use std::fs::File;
use std::io::{BufRead, BufReader};
#
# error_chain! {
#     foreign_links {
#          IOError(::std::io::Error);
#     }
# }

fn run() -> Result<()> {
    let path_to_read = Path::new("new.txt");

    let stdout_handle = Handle::stdout()?;
    let handle = Handle::from_path(path_to_read)?;

    if stdout_handle == handle {
        bail!("You are reading and writing to the same file");
    } else {
        let file = File::open(&path_to_read)?;
        let file = BufReader::new(file);
        for (num, line) in file.lines().enumerate() {
            println!("{} : {}", num, line?.to_uppercase());
        }
    }

    Ok(())
}
#
# quick_main!(run);
cargo run

displays the contents of the file new.txt.

cargo run >> ./new.txt

errors because the two files are same.

Access a file randomly using a memory map

memmap-badge cat-filesystem-badge

Creates a memory map of a file using memmap and simulates some non-sequential reads from the file. Using a memory map means you just index into a slice rather than dealing with seek to navigate a File.

The Mmap::map function assumes the file behind the memory map is not being modified at the same time by another process or else a race condition occurs.

# #[macro_use]
# extern crate error_chain;
extern crate memmap;

use memmap::Mmap;
# use std::fs::File;
# use std::io::Write;
#
# error_chain! {
#     foreign_links {
#         Io(std::io::Error);
#     }
# }

fn run() -> Result<()> {
#     write!(File::create("content.txt")?, "My hovercraft is full of eels!")?;
#
    let file = File::open("content.txt")?;
    let map = unsafe { Mmap::map(&file)? };

    let random_indexes = [0, 1, 2, 19, 22, 10, 11, 29];
    assert_eq!(&map[3..13], b"hovercraft");
    let random_bytes: Vec<u8> = random_indexes.iter()
        .map(|&idx| map[idx])
        .collect();
    assert_eq!(&random_bytes[..], b"My loaf!");
    Ok(())
}
#
# quick_main!(run);