TechLead
Lección 3 de 6
7 min de lectura
Node.js

Sistema de Archivos de Node.js

Trabajar con archivos y directorios en Node.js

# Sistema de Archivos de Node.js El módulo `fs` (file system) de Node.js proporciona una API para interactuar con el sistema de archivos. Aprende a leer, escribir, actualizar y eliminar archivos y directorios. ## Módulo fs Node.js proporciona métodos síncronos y asíncronos para operaciones de archivos: ```javascript // CommonJS const fs = require('fs'); // ES Modules import fs from 'fs'; // API de Promises (recomendado) import fs from 'fs/promises'; ``` ## Lectura de Archivos ### Síncrono (Bloquea el Hilo) ```javascript const fs = require('fs'); try { // Leer archivo completo const data = fs.readFileSync('file.txt', 'utf8'); console.log(data); } catch (err) { console.error('Error al leer archivo:', err); } ``` ### Asíncrono con Callbacks ```javascript const fs = require('fs'); fs.readFile('file.txt', 'utf8', (err, data) => { if (err) { console.error('Error al leer archivo:', err); return; } console.log(data); }); console.log('Este mensaje aparece primero'); ``` ### Asíncrono con Promises (Recomendado) ```javascript const fs = require('fs/promises'); async function readFile() { try { const data = await fs.readFile('file.txt', 'utf8'); console.log(data); } catch (err) { console.error('Error al leer archivo:', err); } } readFile(); ``` ### Leyendo Archivos JSON ```javascript const fs = require('fs/promises'); async function readJSON() { try { const data = await fs.readFile('data.json', 'utf8'); const json = JSON.parse(data); console.log(json); } catch (err) { console.error('Error:', err); } } // O más simple: async function readJSON2() { const json = JSON.parse( await fs.readFile('data.json', 'utf8') ); return json; } ``` ## Escritura de Archivos ### Escribir Archivo Completo ```javascript const fs = require('fs/promises'); async function writeFile() { try { await fs.writeFile('output.txt', '¡Hola, Mundo!', 'utf8'); console.log('¡Archivo escrito exitosamente!'); } catch (err) { console.error('Error al escribir archivo:', err); } } ``` ### Agregar a Archivo ```javascript const fs = require('fs/promises'); async function appendFile() { try { await fs.appendFile('log.txt', 'Nueva línea de log ', 'utf8'); console.log('¡Contenido agregado!'); } catch (err) { console.error('Error:', err); } } ``` ### Escribir Archivos JSON ```javascript const fs = require('fs/promises'); async function writeJSON() { const data = { nombre: 'Juan', edad: 30, ciudad: 'Madrid' }; try { await fs.writeFile( 'user.json', JSON.stringify(data, null, 2), 'utf8' ); console.log('¡JSON guardado!'); } catch (err) { console.error('Error:', err); } } ``` ## Trabajando con Directorios ### Crear Directorio ```javascript const fs = require('fs/promises'); async function createDir() { try { // Crear directorio único await fs.mkdir('nuevo-dir'); // Crear directorios anidados await fs.mkdir('ruta/a/directorio', { recursive: true }); console.log('¡Directorios creados!'); } catch (err) { console.error('Error:', err); } } ``` ### Leer Contenidos del Directorio ```javascript const fs = require('fs/promises'); async function listFiles() { try { const files = await fs.readdir('.'); console.log('Archivos:', files); // Con información de tipo de archivo const entries = await fs.readdir('.', { withFileTypes: true }); entries.forEach(entry => { console.log( entry.name, entry.isDirectory() ? '(directorio)' : '(archivo)' ); }); } catch (err) { console.error('Error:', err); } } ``` ### Eliminar Directorio ```javascript const fs = require('fs/promises'); async function removeDir() { try { // Eliminar directorio vacío await fs.rmdir('empty-dir'); // Eliminar directorio con contenidos await fs.rm('dir-with-files', { recursive: true, force: true }); console.log('¡Directorios eliminados!'); } catch (err) { console.error('Error:', err); } } ``` ## Información de Archivos ### Obtener Estadísticas de Archivo ```javascript const fs = require('fs/promises'); async function getFileInfo() { try { const stats = await fs.stat('file.txt'); console.log('¿Es archivo?', stats.isFile()); console.log('¿Es directorio?', stats.isDirectory()); console.log('Tamaño:', stats.size, 'bytes'); console.log('Creado:', stats.birthtime); console.log('Modificado:', stats.mtime); console.log('Accedido:', stats.atime); } catch (err) { console.error('Error:', err); } } ``` ### Verificar si Existe Archivo ```javascript const fs = require('fs/promises'); async function fileExists(path) { try { await fs.access(path); return true; } catch { return false; } } // Usar if (await fileExists('file.txt')) { console.log('¡El archivo existe!'); } ``` ## Copiar y Mover Archivos ### Copiar Archivo ```javascript const fs = require('fs/promises'); async function copyFile() { try { await fs.copyFile('source.txt', 'destination.txt'); console.log('¡Archivo copiado!'); } catch (err) { console.error('Error:', err); } } ``` ### Mover/Renombrar Archivo ```javascript const fs = require('fs/promises'); async function moveFile() { try { // Renombrar en mismo directorio await fs.rename('old-name.txt', 'new-name.txt'); // Mover a diferente directorio await fs.rename('file.txt', 'carpeta/file.txt'); console.log('¡Archivo movido!'); } catch (err) { console.error('Error:', err); } } ``` ### Eliminar Archivo ```javascript const fs = require('fs/promises'); async function deleteFile() { try { await fs.unlink('file-to-delete.txt'); console.log('¡Archivo eliminado!'); } catch (err) { console.error('Error:', err); } } ``` ## Módulo Path El módulo `path` ayuda a trabajar con rutas de archivo y directorio: ```javascript const path = require('path'); // Unir rutas const filePath = path.join(__dirname, 'data', 'users.json'); // /Users/usuario/proyecto/data/users.json // Resolver ruta absoluta const absolute = path.resolve('data', 'file.txt'); // Obtener extensión const ext = path.extname('file.txt'); // .txt // Obtener nombre de archivo const filename = path.basename('/ruta/a/file.txt'); // file.txt // Obtener directorio const dir = path.dirname('/ruta/a/file.txt'); // /ruta/a // Análisis de ruta const parsed = path.parse('/ruta/a/file.txt'); // { // root: '/', // dir: '/ruta/a', // base: 'file.txt', // ext: '.txt', // name: 'file' // } // Normalizar ruta const normalized = path.normalize('/ruta//a/./file.txt'); // /ruta/a/file.txt ``` ## Ejemplo Práctico: Sistema de Gestión de Archivos ```javascript const fs = require('fs/promises'); const path = require('path'); class FileManager { constructor(baseDir) { this.baseDir = baseDir; } // Asegurar que el directorio base existe async init() { await fs.mkdir(this.baseDir, { recursive: true }); } // Guardar datos JSON async saveJSON(filename, data) { const filePath = path.join(this.baseDir, filename); await fs.writeFile( filePath, JSON.stringify(data, null, 2), 'utf8' ); } // Leer datos JSON async readJSON(filename) { const filePath = path.join(this.baseDir, filename); const data = await fs.readFile(filePath, 'utf8'); return JSON.parse(data); } // Listar todos los archivos async listFiles() { const entries = await fs.readdir(this.baseDir, { withFileTypes: true }); return entries .filter(entry => entry.isFile()) .map(entry => entry.name); } // Eliminar archivo async deleteFile(filename) { const filePath = path.join(this.baseDir, filename); await fs.unlink(filePath); } // Obtener información de archivo async getFileInfo(filename) { const filePath = path.join(this.baseDir, filename); const stats = await fs.stat(filePath); return { nombre: filename, tamaño: stats.size, creado: stats.birthtime, modificado: stats.mtime, esDirectorio: stats.isDirectory() }; } } // Usar async function main() { const fm = new FileManager('./data'); await fm.init(); // Guardar datos await fm.saveJSON('users.json', [ { id: 1, nombre: 'Juan' }, { id: 2, nombre: 'María' } ]); // Leer datos const users = await fm.readJSON('users.json'); console.log('Usuarios:', users); // Listar archivos const files = await fm.listFiles(); console.log('Archivos:', files); // Obtener información const info = await fm.getFileInfo('users.json'); console.log('Info:', info); } main().catch(console.error); ``` ## Manejo de Errores Siempre maneja errores al trabajar con el sistema de archivos: ```javascript const fs = require('fs/promises'); async function safeReadFile(filename) { try { const data = await fs.readFile(filename, 'utf8'); return { success: true, data }; } catch (err) { if (err.code === 'ENOENT') { return { success: false, error: 'Archivo no encontrado' }; } if (err.code === 'EACCES') { return { success: false, error: 'Permiso denegado' }; } return { success: false, error: err.message }; } } // Usar const result = await safeReadFile('file.txt'); if (result.success) { console.log(result.data); } else { console.error(result.error); } ``` ### Códigos de Error Comunes | Código | Significado | |--------|------------| | `ENOENT` | No existe tal archivo o directorio | | `EACCES` | Permiso denegado | | `EEXIST` | El archivo ya existe | | `EISDIR` | Es un directorio | | `ENOTDIR` | No es un directorio | ## Mejores Prácticas 1. **Usar Async/Await**: Preferir métodos asíncronos sobre síncronos 2. **Manejo de Errores**: Siempre usar try/catch con async/await 3. **Usar path.join()**: Para rutas multi-plataforma 4. **Validar Rutas**: Verificar la existencia de archivos antes de operaciones 5. **Streams para Archivos Grandes**: Usar streams para archivos grandes 6. **Cerrar Descriptores de Archivo**: Limpiar después de operaciones ## Recursos - [Documentación de fs](https://nodejs.org/docs/latest/api/fs.html) - [Documentación de path](https://nodejs.org/docs/latest/api/path.html) ¡Domina las operaciones de archivos en Node.js! 📁

Continúa Aprendiendo