Por que trabalhar com arquivos em Rust não é um sofrimento, mas sim um prazer?
\n\nSe você está acostumado com Python, onde open() resolve quase tudo, Rust pode parecer um professor rigoroso. Mas por trás desse rigor esconde-se um poder incrível. Rust não permitirá que você acidentalmente deixe um arquivo aberto, leia bytes como string ou esqueça de verificar se um diretório existe. Neste artigo, vamos explorar o trabalho com arquivos e o sistema de arquivos em Rust — desde operações simples até técnicas avançadas. Você aprenderá como ler, escrever, criar e excluir arquivos, além de gerenciar caminhos de forma eficiente.
Pronto? Vamos lá!
\n\nFundamentos: abrir, ler, fechar
\n\nEm Rust, não existe uma função embutida open() como em Python. Em vez disso, usamos o poderoso módulo std::fs. Vamos começar com o mais simples — ler um arquivo inteiro.
Lendo um arquivo inteiro como string
\n\nA maneira mais simples de ler um arquivo é usar std::fs::read_to_string. É análogo ao file.read() em Python, mas com garantia de segurança.
use std::fs;\n\nfn main() {\n let content = fs::read_to_string("hello.txt")\n .expect("Não foi possível ler o arquivo");\n println!("Conteúdo do arquivo:\\n{}", content);\n}\n\nObserve o .expect(). Em Rust, não há exceções — há Result. Se o arquivo não existir, o programa "trava" com uma mensagem clara. Para código em produção, é melhor usar match ou unwrap_or_else, mas para aprendizado, expect é ideal.
Escrevendo em um arquivo
\n\nA escrita também é intuitiva:
\n\nuse std::fs;\n\nfn main() {\n let data = "Hello, Rust!\\nEsta é uma gravação de teste.";\n fs::write("output.txt", data)\n .expect("Não foi possível escrever o arquivo");\n println!("Arquivo gravado com sucesso!");\n}\n\nO método fs::write cria o arquivo se ele não existir e sobrescreve o conteúdo se o arquivo existir. Para adicionar dados ao final do arquivo, use OpenOptions.
Trabalhando com caminhos: Path e PathBuf
\n\nEm Rust, existem dois tipos principais para trabalhar com caminhos: Path (emprestado, imutável) e PathBuf (próprio, mutável). Entender a diferença entre eles é a chave para trabalhar eficientemente com o sistema de arquivos.
Criação e manipulação de caminhos
\n\nuse std::path::{Path, PathBuf};\n\nfn main() {\n // Criando um caminho\n let path = Path::new("data/subdir/file.txt");\n \n // Obtendo componentes do caminho\n println!("Diretório pai: {:?}", path.parent());\n println!("Nome do arquivo: {:?}", path.file_name());\n println!("Extensão: {:?}", path.extension());\n \n // Montando um novo caminho\n let mut new_path = PathBuf::from("backup");\n new_path.push("data");\n new_path.push("file.txt");\n println!("Novo caminho: {}", new_path.display());\n}\n\nO método .display() é obrigatório se você quiser exibir o caminho no terminal. Rust não permite simplesmente inserir um caminho em uma string — isso é uma proteção contra problemas de codificação.
Leitura e escrita: nível avançado
\n\nQuando você precisa de mais controle, use File e BufReader/BufWriter.
Lendo um arquivo linha por linha
\n\nPara arquivos grandes, ler tudo na memória não é eficiente. Use leitura bufferizada:
\n\nuse std::fs::File;\nuse std::io::{BufRead, BufReader};\n\nfn main() {\n let file = File::open("large_file.txt")\n .expect("Arquivo não encontrado");\n let reader = BufReader::new(file);\n \n for (index, line) in reader.lines().enumerate() {\n let line = line.expect("Erro ao ler linha");\n println!("Linha {}: {}", index + 1, line);\n }\n}\n\nEssa abordagem permite processar arquivos de qualquer tamanho sem carregá-los completamente na memória RAM.
\n\nAdicionando dados ao final do arquivo
\n\n