En Rust, la interacción con el sistema de archivos se gestiona principalmente a través del módulo std::fs. La estructura fundamental es std::fs::File, que representa un manejador para un archivo en el disco. Para abrir un archivo, existen dos caminos principales: File::open(path), que abre el archivo únicamente en modo de lectura, y File::create(path), que lo abre para escritura, pero con una advertencia importante: si el archivo ya existe, su contenido se borrará (truncará).

Cuando necesitas un control más granular, como abrir un archivo para leer y escribir simultáneamente, o simplemente añadir contenido al final de uno existente sin borrar lo anterior (modo append), debes usar OpenOptions. Este constructor permite configurar permisos específicos como .read(true), .write(true), .append(true) o .create(true).

Además de File, el módulo std::fs ofrece funciones de conveniencia para tareas rápidas. Por ejemplo, fs::read_to_string es ideal para cargar archivos de texto directamente en un tipo String, mientras que fs::write permite volcar datos rápidamente sin gestionar manualmente el flujo de apertura y cierre. Si no se gestionan correctamente los errores devueltos por estas operaciones (que retornan io::Result), el programa podría fallar inesperadamente al intentar acceder a rutas inexistentes o sin permisos de administrador.

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

fn main() -> io::Result<()> {
    let path = "ejemplo.txt";
    let path_copia = "copia_ejemplo.txt";

    // 1. Crear un archivo nuevo o truncarlo (borrar contenido existente)
    {
        let mut file = File::create(path)?;
        file.write_all(b"Línea 1: Hola Rust!\n")?;
    }

    // 2. Usar OpenOptions para añadir contenido al final (append)
    {
        let mut file = OpenOptions::new()
            .append(true)
            .open(path)?;
        file.write_all(b"Línea 2: Añadida con OpenOptions.\n")?;
    }

    // 3. Escribir directamente usando la función de conveniencia fs::write
    // Esto sobrescribirá el archivo con el nuevo contenido
    fs::write(path, "Contenido nuevo con fs::write")?;

    // 4. Leer el contenido de un archivo como un String
    let contenido = fs::read_to_string(path)?;
    println!("Contenido actual del archivo: {}", contenido);

    // 5. Copiar el archivo actual a una nueva ubicación
    fs::copy(path, path_copia)?;
    println!("Archivo copiado a: {}", path_copia);

    // 6. Limpieza: Eliminar los archivos creados
    fs::remove_file(path)?;
    fs::remove_file(path_copia)?;
    println!("Archivos eliminados con éxito.");

    Ok(())
}

Explicación del Código

  • path y path_copia: Son variables de tipo &str que contienen las rutas de los archivos que vamos a manipular.
  • File::create(path)?: Crea un archivo en la ruta definida en path. Si el archivo ya existía, se trunca (se vacía). El símbolo ? maneja el io::Result, propagando el error si no se puede crear el archivo.
  • file.write_all(b"...")?: El método write_all de la variable file escribe una secuencia de bytes. El prefijo b convierte el string en un slice de bytes (&[u8]).
  • OpenOptions::new().append(true).open(path)?: Configuramos un objeto OpenOptions para que el archivo se abra en modo “append”. Esto significa que el puntero de escritura se coloca al final, preservando el contenido anterior. El resultado es un objeto de tipo File.
  • fs::write(path, "...")?: Una función de alto nivel que abre el archivo, escribe el contenido proporcionado y lo cierra automáticamente.
  • fs::read_to_string(path)?: Lee todo el contenido del archivo en path y lo devuelve como un String de Rust.
  • fs::copy(path, path_copia)?: Copia el archivo de origen (path) al destino (path_copia).
  • fs::remove_file(path)?: Elimina el archivo físico del sistema de archivos.

90