Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Things on this page are fragmentary and immature notes/thoughts of the author. Please read with your own judgement!

** Things on this page are fragmentary and immature notes/thoughts of the author. Please read with your own judgement! **

:timing
:sccache 1

Tips and Traps

  1. Use buffered IO as much as possible (for performance concerns). However, be aware that BufWriter might not write data into a file until BufWriter.flush is called. This is especially tricky if you explore Rust code in a JupyterLab notebook. If you use BufWriter in a JupyterLab notebook, it is suggested that you either call BufWriter.flush manually

     :::Rust
     let f = File::create("stat.csv").expect("Unable to create file");
     let mut bfw = BufWriter::new(f);
     for (id, n, num_jokers, rank, htype) in &stat {
         bfw.write(format!("{id},{n},{num_jokers},{rank},{htype}\n").as_bytes());
     }
     bfw.flush()

    or you enclose BufWriter in a smaller curly brace scope (to rely on the Drop check to trigger flush).

     :::Rust
     {
       let f = File::create("stat.csv").expect("Unable to create file");
       let mut bfw = BufWriter::new(f);
       for (id, n, num_jokers, rank, htype) in &stat {
           bfw.write(format!("{id},{n},{num_jokers},{rank},{htype}\n").as_bytes());
       }
     }
  2. Key strokes CTRL + D signals an EOF to stdin input.

  3. Methods reading from stdin appends the input to the buffer rather than overwrite it!

  4. Rust crates serde and cron are popular serialization/deserialization libraries.

use std::path::Path;
use std::io::BufReader;
use std::fs::File;
use std::io::Read;
use std::io::Lines;
use std::io::{self, BufReader, BufWriter};
use std::io::prelude::*;
use std::fs::File;
use std::fs;
fs::read_to_string("data.txt")
Err(Os { code: 2, kind: NotFound, message: "No such file or directory" })

std::fs::read

Read the entire contents of a file into a bytes vector. This is a convenience function for using File::open and read_to_end with fewer imports and without an intermediate variable. It pre-allocates a buffer based on the file size when available, so it is generally faster than reading into a vector created with Vec::new().

fs::read("data.txt")
Ok([104, 111, 119, 10, 97, 114, 101, 32, 121, 111, 117, 10, 100, 111, 105, 110, 103])
fs::write("o1.txt", "this is an example line output")
Ok(())

std::fs::File

You can open a file from both a Path and a string.

let f1 = File::open(Path::new("data.txt"));
f1
Ok(File { fd: 3, path: "/workdir/archives/blog/misc/content/2020/11/rust-io/data.txt", read: true, write: false })
let f2 = File::open("data.txt");
f2
Ok(File { fd: 4, path: "/workdir/archives/blog/misc/content/2020/11/rust-io/data.txt", read: true, write: false })

Read text from a file.

let mut f = File::open("data.txt")?;
let mut content = String::new();
f.read_to_string(&mut content)?;
content
"how\nare you\ndoing"

Write text into a file.

let mut file = File::create("output.txt").unwrap();
file
File { fd: 4, path: "/workdir/archives/blog/misc/content/2020/11/rust-io/output.txt", read: false, write: true }
file.write_all(b"Hello, world!");

std::io::BufReader

let br = BufReader::new(File::open("data.txt")?);
for line in br.lines() {
    println!("{:?}", line);
}
Ok("how")
Ok("")
Ok("are you")
Ok("doing")
()
let br = BufReader::new(File::open("data.txt")?);
for (idx, line) in br.lines().enumerate() {
    println!("Line {}: {:?}", idx, line);
}
Line 0: Ok("how")
Line 1: Ok("")
Line 2: Ok("are you")
Line 3: Ok("doing")
()
let br = BufReader::new(File::open("data.txt")?);
for (idx, line) in br.lines().enumerate() {
    println!("Line {}: {:?}", idx, line);
}
Line 0: Ok("how")
Line 1: Ok("")
Line 2: Ok("are you")
Line 3: Ok("doing")
()

std::io::BufWriter

let f = File::create("o2.txt").expect("Unable to create file");
let mut bfw = BufWriter::new(f);
bfw.write_all(b"writing data\nusing std::io::BufWriter")
Ok(())

You have to call the method BufWriter.flush to force the buffer to output immediately.

bfw.flush()
Ok(())

Before a buffer is destructed, its content is output to the file.

{
    let f = File::create("o3.txt").expect("Unable to create file");
    let mut bfw = BufWriter::new(f);
    bfw.write_all(b"writing data\nusing std::io::BufWriter")
}
Ok(())

Read From Stdin

Stdin::read_line reads a line (terminated by \n) and returns a Result object. On success, it returns Ok(n) where n is the number of bytes read from stdin.

let mut buffer = String::new();
let stdin = std::io::stdin();
let r = stdin.read_line(&mut buffer);
!pwd
 ^^^ not found in this scope
cannot find value `pwd` in this scope

Read/Write CSV in Rust

Please refer to Read and Write CSV Files in Rust for details.

Bundle File into Rust Application

Please refer to Bundle Resource Files into a Rust Application for more discussions.

fs::canonicalize("./o1.txt")
Ok("/workdir/archives/blog/misc/content/2020/11/rust-io/o1.txt")
fs::copy("o1.txt", "out1.txt")
Ok(30)
fs::create_dir("my_dir")
Ok(())
fs::create_dir_all("another/dir")
Ok(())
fs::metadata("o1.txt")
Ok(Metadata { file_type: FileType(FileType { mode: 33188 }), is_dir: false, is_file: true, permissions: Permissions(FilePermissions { mode: 33188 }), modified: Ok(SystemTime { tv_sec: 1627506651, tv_nsec: 611396728 }), accessed: Ok(SystemTime { tv_sec: 1627506651, tv_nsec: 987468906 }), created: Err(Error { kind: Other, message: "creation time is not available for the filesystem" }), .. })
fs::read_dir(".")
Ok(ReadDir("."))
for file in fs::read_dir(".").unwrap() {
    println!("{:?}", file);
}
Ok(DirEntry("./.ipynb_checkpoints"))
Ok(DirEntry("./another"))
Ok(DirEntry("./my_dir"))
Ok(DirEntry("./o1.txt"))
Ok(DirEntry("./o2.txt"))
Ok(DirEntry("./o3.txt"))
Ok(DirEntry("./out1.txt"))
Ok(DirEntry("./output.txt"))
Ok(DirEntry("./rust-io.ipynb"))
()
fs::read_link("out2.txt")
Ok("o2.txt")

fs::remove_dir

Removes an empty directory.

fs::remove_dir("another")
Err(Os { code: 39, kind: Other, message: "Directory not empty" })
fs::remove_dir("my_dir")
Ok(())
fs::remove_dir_all("another")
Ok(())
https://doc.rust-lang.org/std/fs/fn.remove_file.html
https://doc.rust-lang.org/std/fs/fn.rename.html