Escrever em Arquivo em Rust
Rust oferece várias formas de escrever em arquivos, desde funções simples de uma linha até escrita bufferizada para alta performance. Vamos explorar cada abordagem.
Escrita simples com fs::write()
A forma mais direta de escrever texto em um arquivo:
use std::fs;
fn main() {
// Cria o arquivo (ou sobrescreve se existir)
fs::write("saida.txt", "Olá, Rust!\nSegunda linha.\n")
.expect("Erro ao escrever arquivo");
println!("Arquivo criado com sucesso!");
// Verificar o conteúdo
let conteudo = fs::read_to_string("saida.txt").unwrap();
println!("Conteúdo:\n{}", conteudo);
}
Saída:
Arquivo criado com sucesso!
Conteúdo:
Olá, Rust!
Segunda linha.
Usando File::create() e write!()
Para mais controle sobre a escrita, use File::create() com as macros write!() e writeln!():
use std::fs::File;
use std::io::{self, Write};
fn main() -> io::Result<()> {
let mut arquivo = File::create("relatorio.txt")?;
writeln!(arquivo, "=== Relatório ===")?;
writeln!(arquivo, "Data: 2026-02-23")?;
writeln!(arquivo)?; // linha em branco
// Escrever dados formatados
let itens = vec![
("Notebook", 3, 4599.90),
("Mouse", 15, 89.99),
("Teclado", 8, 249.50),
];
writeln!(arquivo, "{:<15} {:>5} {:>10}", "Produto", "Qtd", "Preço")?;
writeln!(arquivo, "{}", "-".repeat(32))?;
let mut total = 0.0;
for (nome, qtd, preco) in &itens {
let subtotal = *qtd as f64 * preco;
writeln!(arquivo, "{:<15} {:>5} {:>10.2}", nome, qtd, subtotal)?;
total += subtotal;
}
writeln!(arquivo, "{}", "-".repeat(32))?;
writeln!(arquivo, "{:<15} {:>5} {:>10.2}", "TOTAL", "", total)?;
println!("Relatório gerado em relatorio.txt");
// Mostrar resultado
let conteudo = std::fs::read_to_string("relatorio.txt")?;
println!("\n{}", conteudo);
Ok(())
}
Saída:
Relatório gerado em relatorio.txt
=== Relatório ===
Data: 2026-02-23
Produto Qtd Preço
--------------------------------
Notebook 3 13799.70
Mouse 15 1349.85
Teclado 8 1996.00
--------------------------------
TOTAL 17145.55
Escrita bufferizada com BufWriter
Para muitas operações de escrita pequenas, BufWriter melhora significativamente a performance:
use std::fs::File;
use std::io::{self, BufWriter, Write};
fn main() -> io::Result<()> {
let arquivo = File::create("dados_grandes.txt")?;
let mut escritor = BufWriter::new(arquivo);
// Escrever muitas linhas — BufWriter acumula em buffer
for i in 1..=10_000 {
writeln!(escritor, "Linha {}: dado_{}", i, i * 7)?;
}
// O flush é automático quando BufWriter sai de escopo,
// mas você pode forçar:
escritor.flush()?;
println!("Escritas 10.000 linhas com BufWriter");
// BufWriter com tamanho de buffer personalizado
let arquivo = File::create("custom_buffer.txt")?;
let mut escritor = BufWriter::with_capacity(64 * 1024, arquivo); // 64KB
for i in 1..=1000 {
writeln!(escritor, "Entrada {}: valor={:.4}", i, i as f64 * 0.001)?;
}
escritor.flush()?;
println!("Escritas 1.000 linhas com buffer de 64KB");
Ok(())
}
Saída:
Escritas 10.000 linhas com BufWriter
Escritas 1.000 linhas com buffer de 64KB
Modo Append (adicionar ao final)
Para adicionar conteúdo sem apagar o existente, use OpenOptions com .append(true):
use std::fs::{self, OpenOptions};
use std::io::{self, Write};
fn adicionar_log(mensagem: &str) -> io::Result<()> {
let mut arquivo = OpenOptions::new()
.create(true) // cria se não existir
.append(true) // adiciona ao final
.open("app.log")?;
writeln!(arquivo, "[2026-02-23 10:30:00] {}", mensagem)?;
Ok(())
}
fn main() -> io::Result<()> {
// Criar arquivo inicial
fs::write("app.log", "")?;
// Adicionar várias entradas
adicionar_log("Aplicação iniciada")?;
adicionar_log("Conexão com banco estabelecida")?;
adicionar_log("Servidor escutando na porta 8080")?;
adicionar_log("Primeira requisição recebida")?;
// Mostrar resultado
let conteudo = fs::read_to_string("app.log")?;
println!("Conteúdo do log:\n{}", conteudo);
Ok(())
}
Saída:
Conteúdo do log:
[2026-02-23 10:30:00] Aplicação iniciada
[2026-02-23 10:30:00] Conexão com banco estabelecida
[2026-02-23 10:30:00] Servidor escutando na porta 8080
[2026-02-23 10:30:00] Primeira requisição recebida
Escrever bytes (arquivo binário)
Para dados que não são texto, escreva bytes diretamente:
use std::fs::File;
use std::io::{self, Write};
fn main() -> io::Result<()> {
// Escrever bytes diretamente
let dados: Vec<u8> = (0..=255).collect();
fs::write("binario.dat", &dados)?;
println!("Escritos {} bytes em binario.dat", dados.len());
// Escrever struct como bytes
let mut arquivo = File::create("numeros.bin")?;
let numeros: Vec<f64> = vec![3.14, 2.71, 1.41, 1.73];
for num in &numeros {
arquivo.write_all(&num.to_le_bytes())?;
}
println!("Escritos {} f64 em numeros.bin", numeros.len());
Ok(())
}
Saída:
Escritos 256 bytes em binario.dat
Escritos 4 f64 em numeros.bin
Criar diretórios antes de escrever
Garanta que o diretório existe antes de criar o arquivo:
use std::fs;
use std::io::{self, Write};
use std::path::Path;
fn escrever_com_diretorios(caminho: &str, conteudo: &str) -> io::Result<()> {
// Criar diretórios intermediários se necessário
if let Some(pai) = Path::new(caminho).parent() {
fs::create_dir_all(pai)?;
}
fs::write(caminho, conteudo)
}
fn main() -> io::Result<()> {
escrever_com_diretorios(
"saida/logs/2026/02/app.log",
"Log de exemplo\n",
)?;
println!("Arquivo criado com diretórios intermediários");
Ok(())
}
Saída:
Arquivo criado com diretórios intermediários
Resumo dos métodos
| Método | Quando usar |
|---|---|
fs::write() | Escrever conteúdo completo de uma vez |
File::create() + write!() | Escrita formatada incremental |
BufWriter | Muitas escritas pequenas (performance) |
OpenOptions::append | Adicionar ao final do arquivo |
write_all(&bytes) | Dados binários |
Veja também
- Ler Arquivo em Rust — a operação complementar de leitura
- Ler Arquivo CSV — leia e processe dados tabulares
- Formatar Strings — formate dados antes de escrever
- Serializar Struct para JSON — escreva dados como JSON em arquivo
- Conectar ao PostgreSQL — persista dados em banco ao invés de arquivo
- Documentação oficial:
std::fs::File