¿Por qué trabajar con archivos en Rust no es un dolor, sino un placer?
\n\nSi estás acostumbrado a Python, donde open() resuelve casi todo, Rust puede parecer un profesor estricto. Pero detrás de esta rigurosidad se esconde un poder increíble. Rust no te permitirá dejar accidentalmente un archivo abierto, leer bytes como si fueran una cadena u olvidar verificar si un directorio existe. En este artículo analizaremos el trabajo con archivos y el sistema de archivos en Rust, desde operaciones simples hasta técnicas avanzadas. Aprenderás a leer, escribir, crear y eliminar archivos, así como a gestionar rutas de manera eficiente.
¿Listo? ¡Allá vamos!
\n\nFundamentos: abrir, leer, cerrar
\n\nEn Rust no hay una función incorporada open() como en Python. En su lugar, usamos el potente módulo std::fs. Comencemos con lo más simple: leer un archivo completo.
Leer todo el archivo en una cadena
\n\nLa forma más sencilla de leer un archivo es usar std::fs::read_to_string. Es análogo a file.read() en Python, pero con garantías de seguridad.
use std::fs;\n\nfn main() {\n let content = fs::read_to_string("hello.txt")\n .expect("No se pudo leer el archivo");\n println!("Contenido del archivo:\\n{}", content);\n}\n\nObserva el .expect(). En Rust no hay excepciones, hay Result. Si el archivo no existe, el programa "fallará" con un mensaje claro. Para código de producción es mejor usar match o unwrap_or_else, pero para aprender, expect es ideal.
Escribir en un archivo
\n\nLa escritura también es intuitiva:
\n\nuse std::fs;\n\nfn main() {\n let data = "¡Hola, Rust!\\nEsta es una escritura de prueba.";\n fs::write("output.txt", data)\n .expect("No se pudo escribir el archivo");\n println!("¡Archivo escrito exitosamente!");\n}\n\nEl método fs::write crea el archivo si no existe y sobrescribe el contenido si el archivo ya existe. Para agregar datos al final del archivo, usa OpenOptions.
Trabajo con rutas: Path y PathBuf
\n\nEn Rust hay dos tipos principales para trabajar con rutas: Path (prestado, inmutable) y PathBuf (propietario, mutable). Entender la diferencia entre ellos es clave para trabajar eficientemente con el sistema de archivos.
Creación y manipulación de rutas
\n\nuse std::path::{Path, PathBuf};\n\nfn main() {\n // Crear una ruta\n let path = Path::new("data/subdir/file.txt");\n \n // Obtener componentes de la ruta\n println!("Directorio padre: {:?}", path.parent());\n println!("Nombre del archivo: {:?}", path.file_name());\n println!("Extensión: {:?}", path.extension());\n \n // Construir una nueva ruta\n let mut new_path = PathBuf::from("backup");\n new_path.push("data");\n new_path.push("file.txt");\n println!("Nueva ruta: {}", new_path.display());\n}\n\nEl método .display() es obligatorio si quieres imprimir la ruta en la terminal. Rust no permite simplemente insertar una ruta en una cadena: es una protección contra problemas de codificación.
Lectura y escritura: nivel avanzado
\n\nCuando necesites más control, usa File y BufReader/BufWriter.
Lectura de un archivo línea por línea
\n\nPara archivos grandes, leer todo en memoria no es eficiente. Usa la lectura con búfer:
\n\nuse std::fs::File;\nuse std::io::{BufRead, BufReader};\n\nfn main() {\n let file = File::open("large_file.txt")\n .expect("Archivo no encontrado");\n let reader = BufReader::new(file);\n \n for (index, line) in reader.lines().enumerate() {\n let line = line.expect("Error al leer la línea");\n println!("Línea {}: {}", index + 1, line);\n }\n}\n\nEste enfoque permite procesar archivos de cualquier tamaño sin cargarlos completamente en la memoria RAM.
\n\nAgregar datos al final de un archivo
\n\n