io::Write în Rust

Trait-ul oricărei destinații de octeți: write_all scrie tot bufferul, flush golește memoria tampon; permite write!.

Sintaxă
use std::io::Write;

fn write(&mut self, buf: &[u8]) -> io::Result<usize>
fn write_all(&mut self, buf: &[u8]) -> io::Result<()>
fn flush(&mut self) -> io::Result<()>

Ce face io::Write

Write este implementat de File, Stdout, BufWriter, Vec<u8>, conexiuni de rețea. write(buf) poate scrie doar o parte și spune câți octeți; de aceea în practică folosești write_all(buf), care repetă până scrie tot.

flush() trimite imediat datele aflate în buffere intermediare (BufWriter, ieșirea standard). Macro-urile write! și writeln! formatează text direct într-un Write, la fel ca println!.

Funcțiile care primesc impl Write pot scrie oriunde: într-un fișier, pe ecran sau, în teste, într-un Vec<u8>.

Parametri

Parametru Descriere
buf Octeții de scris.

Ce returnează

write: octeții scriși. write_all și flush: io::Result<()>.

Exemple

Exemplul 1: Același cod, două destinații

scrie_bon nu știe unde scrie. Îl apelăm o dată cu ieșirea standard și o dată cu un Vec<u8>.

use std::io::{self, Write};

fn scrie_bon(mut iesire: impl Write, produse: &[(&str, f64)]) -> io::Result<()> {
    let mut total = 0.0;
    for (nume, pret) in produse {
        writeln!(iesire, "{nume:<10} {pret:>7.2} lei")?;
        total += pret;
    }
    writeln!(iesire, "{:<10} {total:>7.2} lei", "TOTAL")?;
    iesire.flush()
}

fn main() -> io::Result<()> {
    let produse = [("cafea", 24.9), ("croissant", 8.5)];
    scrie_bon(io::stdout(), &produse)?;

    let mut memorie: Vec<u8> = Vec::new();
    scrie_bon(&mut memorie, &produse)?;
    println!("în memorie: {} octeți, {} linii", memorie.len(), memorie.split(|b| *b == b'\n').filter(|l| !l.is_empty()).count());
    Ok(())
}

Rezultat

cafea        24.90 lei
croissant     8.50 lei
TOTAL        33.40 lei
în memorie: 69 octeți, 3 linii

Exemplul 2: write_all cu octeți

use std::fs::{self, File};
use std::io::{self, Write};

fn main() -> io::Result<()> {
    let mut f = File::create("salut.txt")?;
    f.write_all(b"Salut")?;
    f.write_all(", Cluj!\n".as_bytes())?;
    f.flush()?;
    print!("{}", fs::read_to_string("salut.txt")?);
    Ok(())
}

Rezultat

Salut, Cluj!

Greșeli frecvente

  • Folosești write și ignori numărul returnat: o parte din date poate să nu fi fost scrisă. Folosește write_all.
  • Uiți use std::io::Write;: writeln!(f, ...) dă eroarea cannot write into `File`.

Comenzi înrudite

  • 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.
  • io::BufWriter: Adaugă un buffer peste orice scriitor: strânge scrierile mici și le trimite în bucăți mari, mult mai rapid.
  • io::stdout: Ieșirea standard ca obiect Write: permite flush(), write! și scriere rapidă prin lock().
  • File: Un fișier deschis: File::open îl deschide pentru citire, File::create îl creează (sau golește) pentru scriere.