io::BufReader în Rust

Adaugă un buffer peste orice cititor (de obicei un File): citiri mai rapide și acces la metodele BufRead.

Sintaxă
use std::io::BufReader;

fn new(inner: R) -> BufReader<R>          // R: Read
fn with_capacity(capacity: usize, inner: R) -> BufReader<R>

Ce face io::BufReader

BufReader::new(f) împachetează un cititor (File, TcpStream etc.) și citește din el în bucăți mari, de 8 KB implicit. Citirile mici pe care le faci tu se servesc apoi din memorie, fără un apel de sistem de fiecare dată.

Pe lângă viteză, BufReader implementează BufRead, deci primești lines(), read_line() și read_until(). Este calea obișnuită de a citi fișiere mari linie cu linie.

Parametri

Parametru Descriere
inner Cititorul împachetat: orice tip care implementează Read.

Ce returnează

Un BufReader<R>.

Exemple

Exemplul 1: Găsirea liniilor cu erori într-un jurnal

use std::fs::{self, File};
use std::io::{self, BufRead, BufReader};

fn main() -> io::Result<()> {
    fs::write(
        "server.log",
        "INFO pornire\nEROARE conexiune refuzată\nINFO cerere /acasa\nEROARE timeout la baza de date\n",
    )?;

    let cititor = BufReader::new(File::open("server.log")?);
    let erori: Vec<String> = cititor
        .lines()
        .map_while(Result::ok)
        .filter(|l| l.starts_with("EROARE"))
        .collect();

    println!("{} erori:", erori.len());
    for e in erori {
        println!("  {e}");
    }
    Ok(())
}

Rezultat

2 erori:
  EROARE conexiune refuzată
  EROARE timeout la baza de date

Exemplul 2: Citire până la un separator cu read_until

Datele sunt separate prin ;. read_until citește octeți până la separator, inclusiv.

use std::io::{self, BufRead, BufReader};

fn main() -> io::Result<()> {
    let date: &[u8] = b"Ana;Mihai;Ioana;";
    let mut cititor = BufReader::new(date);
    let mut bucata = Vec::new();
    while cititor.read_until(b';', &mut bucata)? > 0 {
        let nume = String::from_utf8_lossy(&bucata);
        println!("{}", nume.trim_end_matches(';'));
        bucata.clear();
    }
    Ok(())
}

Rezultat

Ana
Mihai
Ioana

Greșeli frecvente

  • Creezi un BufReader nou la fiecare citire din același fișier: datele aflate deja în bufferul vechi se pierd. Creează-l o dată și refolosește-l.
  • Folosești BufReader pentru a citi tot fișierul dintr-odată: fs::read_to_string este mai simplu.

Comenzi înrudite

  • io::BufRead: Trait-ul cititorilor cu buffer: oferă citire pe linii (lines, read_line) pentru fișiere, stdin și octeți din memorie.
  • File: Un fișier deschis: File::open îl deschide pentru citire, File::create îl creează (sau golește) pentru scriere.
  • io::BufWriter: Adaugă un buffer peste orice scriitor: strânge scrierile mici și le trimite în bucăți mari, mult mai rapid.
  • io::Read: Trait-ul oricărei surse de octeți (fișier, stdin, rețea): read_to_string și read_to_end citesc tot ce a rămas.