Node
Tutorial Node: Módulo fs
Node.js: Descubre cómo manejar ficheros eficazmente usando fs, streams y promesas en su última versión. Ideal para optimizar proyectos.
Aprende Node GRATIS y certifícateLectura y escritura de archivos
En Node.js, el módulo fs
permite acceder al sistema de archivos para leer y escribir ficheros de forma sincrónica o asíncrona. La lectura sincrónica se realiza mediante métodos como readFileSync
, que bloquean el flujo hasta que se completa la operación y devuelven el contenido del archivo. Por otro lado, readFile
representa la variante asíncrona, que no interrumpe la ejecución del resto del programa.
Para leer un archivo de texto, se recomienda especificar la codificación adecuada, por ejemplo 'utf8'
, para obtener un resultado legible. Un ejemplo sencillo de lectura asíncrona es el siguiente:
import { readFile } from 'fs';
readFile('ruta/del/archivo.txt', 'utf8', (error, datos) => {
if (error) {
console.error("Ocurrió un error al leer el archivo:", error);
return;
}
console.log("Contenido del archivo:", datos);
});
La escritura sigue el mismo esquema de métodos sincrónicos y asíncronos. Con writeFileSync
, se detiene la ejecución hasta finalizar la operación, mientras que writeFile
se ejecuta en segundo plano. Para escribir una cadena en un archivo se puede proceder de la siguiente manera:
import { writeFile } from 'fs';
writeFile('ruta/del/archivo.txt', 'Información nueva', 'utf8', (error) => {
if (error) {
console.error("Hubo un problema al escribir el archivo:", error);
return;
}
console.log("Archivo escrito correctamente");
});
Cuando se trabajan con datos binarios, se omite la especificación de codificación y el contenido se maneja como Buffer
, lo cual resulta apropiado para tratamientos de imágenes u otros formatos no textuales. Este enfoque garantiza un control más detallado sobre la lectura y escritura de cada byte en el archivo.
Streams de lectura/escritura grandes
En Node.js, la gestión de ficheros muy extensos se realiza con flujos que procesan los datos por partes en lugar de cargarlos completos en memoria. Este enfoque permite iniciar la lectura incluso antes de que se haya transferido el archivo por completo, lo que resulta esencial para un rendimiento estable.
Los streams se manejan con métodos como fs.createReadStream
y fs.createWriteStream
, que proporcionan eventos que indican la llegada de cada segmento de datos. Al reaccionar a eventos como data
, end
y error
, se puede diseñar un flujo efectivo que lea y escriba de forma continua sin saturar los recursos del servidor.
Cuando se trata de chunks que superan cientos de megabytes, un enfoque basado en streams puede evitar bloqueos en el bucle de eventos.
Un ejemplo básico de lectura y escritura con streams incluye el encadenamiento mediante pipe()
:
import { createReadStream, createWriteStream } from 'fs';
const lector = createReadStream('archivo-grande.txt');
const escritor = createWriteStream('copia-archivo.txt');
lector.pipe(escritor);
lector.on('error', (err) => {
console.error('Error durante la lectura:', err);
});
escritor.on('error', (err) => {
console.error('Error durante la escritura:', err);
});
Para controlar backpressure, se puede usar pause()
y resume()
en el stream de lectura o bien manejar los eventos drain
y data
de forma manual. Esto contribuye a un flujo equilibrado que no congestione el proceso cuando la escritura sea más lenta que la lectura.
Algunas recomendaciones frecuentes al trabajar con streams incluyen:
- Configurar manejadores de eventos para capturar errores posibles.
- Manejar de forma adecuada la finalización del stream con el evento
end
. - Usar
highWaterMark
en escenarios que requieran un control preciso de la cantidad de datos almacenados temporalmente.
Uso de fs.promises
vs callbacks
El principal motivo para utilizar promesas en lugar de callbacks es la mejora en la legibilidad y mantenimiento del código. Con callbacks, el flujo asíncrono puede volverse difícil de seguir, mientras que las promesas permiten encadenar operaciones y manejar excepciones con una sintaxis más clara.
Cuando se recurre a la versión fs.promises
, se emplea async/await
para escribir código asíncrono de forma más lineal. Un ejemplo mínimo para leer un fichero sería el siguiente, donde se evita la anidación de funciones de callback:
import { readFile } from "fs/promises";
async function leerArchivo(ruta) {
try {
const contenido = await readFile(ruta, "utf8");
console.log("Datos obtenidos:", contenido);
} catch (error) {
console.error("Error al leer:", error);
}
}
Asimismo, el uso de promesas facilita capturar y propagar errores simultáneamente. Basta con ejecutar múltiples operaciones dentro de bloques try/catch
o usando métodos como Promise.all
cuando se precise ejecutar tareas en paralelo. Esta estrategia, frente al manejo de múltiples callbacks, contribuye a minimizar la complejidad en los proyectos de Node.js.
Además, mantener un estilo consistente en toda la base de código ayuda a unificar la forma de trabajar con operaciones de E/S. Con fs.promises, se obtiene un enfoque cohesivo para la interacción con el sistema de archivos en un entorno de desarrollo que requiera operaciones concurrentes más ordenadas.
Todas las lecciones de Node
Accede a todas las lecciones de Node y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Node.js
Introducción Y Entorno
Fundamentos Del Entorno Node.js
Introducción Y Entorno
Módulo Http Y Https
Http Y Api Rest
Http Params, Headers Y Body
Http Y Api Rest
Validación De Datos
Http Y Api Rest
Conexión A Bases De Datos Sin Orm
Persistencia
Creación De Consultas Básicas (Crud) Sin Orm
Persistencia
Módulo Fs
Sistema De Archivos
Introducción A La Seguridad
Seguridad
Sesiones Y Cookies
Seguridad
Roles Y Permisos
Seguridad
Testing En Node.js
Testing
Estructura De Carpetas
Arquitectura
Configuración Y Variables De Entorno
Arquitectura
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender la biblioteca fs de Node.js para manejar archivos.
- Diferenciar entre operaciones sincrónicas y asíncronas.
- Implementar operaciones con
fs.promises
y callbacks. - Gestionar lectura y escritura de streams.
- Aplicar 'backpressure' en streams grandes.
- Capturar y manejar errores en flujos de datos.