Outline

  • Chương 0: Thao tác với File
  • Chương 1: Thao tác với thư mục
  • Chương 2: Text Processing
  • Chương 3: Một số thư viện

References:

Chương 0: Thao tác với File

Các kiểu thao tác vói file

  • Mở một file
  • Tạo mới một file
  • Đóng một file
  • Ghi tới file
  • Đọc metadata từ file
  • Đọc dữ liệu từ file

Eg 1:

Eg 2: Tạo một file mới và ghi

Chú ý hàm write cần mảng các bytes &[u8]

Mở một file

let f = File::open("hello.txt").expect("Could not open file");

Cách khác sử dụng OpenOptions

fn open_with_open_options() {
    let file = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open("foo.txt")
        .unwrap();
}
   
  • Mở với quyền đọc, ghi, ghi thêm
pub fn read(&mut self, read: bool) -> &mut Self
pub fn write(&mut self, write: bool) -> &mut Self
pub fn append(&mut self, append: bool) -> &mut Self
pub fn truncate(&mut self, truncate: bool) -> &mut Self
pub fn create(&mut self, create: bool) -> &mut Self
pub fn create_new(&mut self, create_new: bool) -> &mut Self

Khác nhau của createcreate_newcreate_new sẽ lỗi nếu file đã tồn tại

Tạo một file mới

fn create_file() {
    let mut f = File::create("hello2.txt").expect("Could not create file");
}

Đóng một file

fn write_file() {
    let mut f = File::create("hello2.txt").expect("Could not create file");
    f.write("buffer".as_bytes())
        .expect("Could not write to file");

    f.close();
}

Ghi tới file

fn write_file() {
    let mut f = File::create("hello2.txt").expect("Could not create file");
    f.write("buffer".as_bytes())
        .expect("Could not write to file");
}

Đọc metadata của file

  • File type
  • is dir or not?
  • symbol link ?
  • len
  • permission
  • modified time
  • access time
  • created time

fn main() -> std::io::Result<()> {
    use std::fs;

    let metadata = fs::metadata("foo.txt")?;

    println!("{:?}", metadata.file_type());
    assert!(!metadata.is_dir());
    Ok(())
}

refer: https://doc.rust-lang.org/std/fs/struct.Metadata.html

Đọc dữ liệu từ file

  • Đọc theo từng single byte
  • Đọc vào buffer
  • Đọc theo từng chunk bytes
  • Đọc theo từng dòng
  • Đọc đến cuối
  • Đọc từ cuối (Di chuyển con trỏ để đọc)

Đọc theo từng single byte

fn read_with_single_bytes() {
    let mut file = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open("hello.txt")
        .unwrap();
    for i in file.bytes() {
        println!("Byte: {:?}", i.unwrap());
    }
}

Đọc vào buffer

fn read_with_single_bytes() {
    let mut file = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open("hello.txt")
        .unwrap();

    let mut buffer = [0; 10];
    file.read(&mut buffer).unwrap();
    println!("Buffer contents: {:?}", buffer);
}

Đọc theo từng chunk bytes

fn read_with_buffer() {
    let mut file = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open("hello.txt")
        .unwrap();

    let mut buffer = [0; 10];
    file.read(&mut buffer).unwrap();
    println!("Buffer contents: {:?}", buffer);
}

Đọc đến cuối

Nó nhận đầu vào là 1 vector

fn read_to_end() {
    let mut file = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open("hello.txt")
        .unwrap();

    let mut buffer = vec![0; 1000];
    file.read_to_end(&mut buffer).unwrap();
    println!("Buffer contents: {:?}", buffer);
}

Đọc từ cuối (Di chuyển con trỏ để đọc)

fn read_with_reader4_from_end() {
    let file = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open("hello.txt")
        .unwrap();
    const CAP: usize = 1024 * 128; // 128 KB
    let mut reader = BufReader::with_capacity(CAP, file);
    // let mut reader = BufReader::new(file);
    let r = reader.seek(std::io::SeekFrom::End(0));
    let mut buf = String::new();
    reader.seek_relative(-10);
    reader.read_to_string(&mut buf);
    println!("Line: {:?}", buf);
}

Đọc sử dụng BufReader

  • fill_buf: Trở về nội dung của buffer bên trong, fill it với nhiều dữ liệu nhất
  • consume: Nói rằng buffer đã tiêu thụ n bytes và không được trở về từ hàm read nữa.
  • read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize>: Đọc đến ký tự byte thì dừng lại
  • skip_until: Bỏ qua đến khi gặp ký tự
  • read_lin đọc đến khi gặp 0xA thì dừng
  • rewind: Quay lại đầu file, stream
  • seek: Di chuyển con trỏ đọc đến vị trí
  pub enum SeekFrom {
    Start(u64),
    End(i64),
    Current(i64),
}

Homework 1.1: Read the n th last line of a file

Homework 1.2: Figure out about std::path::Path

Chương 1: Thao tác với thư mục

https://rust-lang-nursery.github.io/rust-cookbook/file/dir.html

List các danh sách files từ một folder

  • Cách 1: Hàm fs::read_dir
fn dir_read_paths() {
    let paths = fs::read_dir("./").unwrap();
    for path in paths {
        println!("Name: {}", path.unwrap().path().display())
    }
}
  • Cách 2:
use glob::glob;
fn main() {
    for e in glob("../*").expect("Failed to read glob pattern") {
        println!("{}", e.unwrap().display());
    }
}
  • Cách 3:
use walkdir::WalkDir;
fn main() {
    for e in WalkDir::new(".").into_iter().filter_map(|e| e.ok()) {
        if e.metadata().unwrap().is_file() {
            println!("{}", e.path().display());
        }
    }
}

List recusely files

fn recurse(path: impl AsRef<Path>) -> Vec<PathBuf> {
    let Ok(entries) = read_dir(path) else { return vec![] };
    entries.flatten().flat_map(|entry| {
        let Ok(meta) = entry.metadata() else { return vec![] };
        if meta.is_dir() { return recurse(entry.path()); }
        if meta.is_file() { return vec![entry.path()]; }
        vec![]
    }).collect()
}

Homework 2: Read the n th last line of a file

Chương 2: Text Processing

Homework 3: Read the n th last line of a file

Regex

Json file