Introducción: por qué trabajar con archivos en JavaScript es imprescindible
\n\nImagina que eres el capitán de una nave espacial. Tu tarea es gestionar las bodegas de carga, las reservas de oxígeno y el diario de a bordo. En el mundo del desarrollo web, el sistema de archivos son esas bodegas, y JavaScript es tu panel de control. Sin la habilidad de trabajar con archivos, te quedarás atrapado en órbita: no podrás guardar las configuraciones del usuario, cargar la configuración del servidor ni procesar archivos de registro.
\n\nMuchos principiantes piensan que JavaScript solo vive en el navegador y no puede tocar archivos en el disco. ¡Eso es un mito! Con la llegada de Node.js (e incluso en los navegadores modernos a través de File API), JavaScript se ha convertido en una herramienta completa para trabajar con el sistema de archivos. Hoy veremos cómo leer, escribir, eliminar y mover archivos, y cómo no caer en la trampa de la asincronía.
\n\nPor cierto, si estás comenzando tu camino en la programación, te recomiendo primero estudiar los fundamentos de JavaScript — esto te ayudará a entender más rápido los ejemplos a continuación.
\n\n¿Dónde trabaja JavaScript con archivos? Dos mundos — dos enfoques
\n\nAntes de sumergirnos en el código, aclaremos: las operaciones con archivos en JS se dividen en dos vertientes.
\n\n1. JavaScript del lado del servidor (Node.js)
\nAquí tenemos acceso completo al sistema de archivos: crear, eliminar, renombrar, leer flujos — todo lo que desees. Trabajamos a través del módulo incorporado fs (File System). Es como una navaja suiza para trabajar con archivos.
2. JavaScript del lado del cliente (navegador)
\nEl navegador es un "entorno aislado" con restricciones. No puedes simplemente tomar y leer cualquier archivo del ordenador del usuario (de lo contrario, los hackers estarían de celebración). Pero puedes trabajar con archivos que el usuario haya seleccionado a través de <input type="file">, o mediante las API FileReader y Blob.
En este artículo nos centraremos en Node.js, pero al final daremos un bono: un ejemplo para el navegador.
\n\nMódulo fs: tu herramienta principal
\n\nEn Node.js, el trabajo con archivos comienza importando el módulo fs:
const fs = require('fs'); // estilo antiguo\n// o\nimport fs from 'fs'; // si usas módulos ES\n\nfs tiene tres modos de funcionamiento: síncrono, asíncrono con callbacks y asíncrono con promesas. Usaremos este último — con async/await, ya que es un enfoque moderno y legible.
Lectura de archivos: de lo simple a lo complejo
\n\nSupongamos que tenemos un archivo data.txt con texto. La forma más simple de leerlo:
import { readFile } from 'fs/promises';\n\nasync function readMyFile() {\n try {\n const data = await readFile('data.txt', 'utf-8');\n console.log(data);\n } catch (err) {\n console.error('Error de lectura:', err.message);\n }\n}\n\nreadMyFile();\n\n¿Qué es importante aquí? 'utf-8' — la codificación. Si no la especificas, obtendrás un buffer sin procesar (Buffer) que deberás convertir a cadena. Para archivos de texto, siempre especifica la codificación.
Si el archivo es grande (por ejemplo, un archivo de registro de 500 MB), leerlo por completo es una mala idea. Aquí es donde los flujos (streams) vienen al rescate:
\n\nimport { createReadStream } from 'fs';\nimport { createInterface } from 'readline';\n\nasync function readLargeFile() {\n const stream = createReadStream('bigfile.log', 'utf-8');\n const rl = createInterface({ input: stream });\n\n for await (const line of rl) {\n console.log('Línea:', line);\n // Procesamos cada línea a medida que se lee\n }\n}\n\nreadLargeFile();\n\nEscritura en archivos: crear y añadir
\n\nLa escritura es de dos tipos: sobrescritura (write) y añadido (append). La diferencia es obvia: write borrará el archivo antiguo, append añadirá al final.
import { writeFile, appendFile } from 'fs/promises';\n\n//