Antes de meternos en algún proyecto más avanzado con Node, vamos a aprender a leer ficheros de texto utilizando la API fs
de NodeJS. Como siempre, la importaremos utilizando node:fs
y utilizaremos un método llamado readFile
.
Vamos a comenzar teniendo en cuenta que tenemos un fichero llamado file.txt
que contiene varias líneas de texto con una frase en cada una.
El método readFile
/ readFileSync
En NodeJS podemos utilizar dos formas de leer un fichero, readFile
(versión asíncrona) y readFileSync
(versión síncrona). Aquí puedes ver un ejemplo sencillo que lee el contenido del fichero de texto:
// Utilizamos readFile (asíncrono)
import { readFile } from "node:fs/promises";
import { styleText } from "node:util";
const FILE = "./file.txt";
const fileContent = await readFile(FILE, { encoding: "utf-8" });
const lines = fileContent.trim().split("\n");
console.log(styleText("magenta", "El contenido del fichero:"));
console.log(lines);
// Utilizamos readFileSync (síncrono)
import { readFileSync } from "node:fs";
import { styleText } from "node:util";
const FILE = "./file.txt";
const fileContent = readFileSync(FILE, { encoding: "utf-8" });
const lines = fileContent.trim().split("\n");
console.log(styleText("magenta", "El contenido del fichero:"));
console.log(lines);
Observa que al usar readFile()
le pasamos la ruta del fichero, así como un objeto de opciones donde le indicamos la codificación del fichero (generalmente, utf-8). En la siguiente línea hacemos un trim()
para eliminar los espacios sobrantes al principio o final del texto.
Finalmente, dividimos el contenido por cada línea, separando por \n
, es decir, por los saltos de línea (ENTER), y los mostramos por pantalla.
Observa las diferencias de la versión síncrona, que se llama readFileSync()
y la versión asíncrona, donde se usa await
y se importa de node:fs/promises
.
Aunque tenemos un método asíncrono
readFile
ennode:fs
, funciona mediante callbacks, y hoy en día, lo ideal sería utilizar elreadFile
asíncrono denode:fs/promises
, ya que tiene integración con promesas y es mucho más cómodo.
De la misma forma que tenemos un readFile()
y un readFileSync()
, también tenemos un writeFile()
y un writeFileSync()
que funcionan de forma muy parecida y siguen la misma lógica. En este caso, el primer parámetro es la ruta del fichero, el segundo parámetro es el contenido que quieres guardar en el fichero, y el tercero es el objeto de opciones.
El método readdir()
Con el método readdir()
podemos leer los archivos (y carpetas) que contiene una ruta indicada. Dicha ruta la obtenemos con el método cwd()
, que nos devuelve la ruta actual donde nos encontramos al ejecutar el programa.
El método readdir()
nos devuelve un array de recursive
para que revise las subcarpetas interiores y withFileTypes
para que devuelva un objeto con partes separadas en lugar de un
import { cwd } from "node:process";
import { readdir } from "node:fs/promises";
import { styleText } from "node:util";
const CURRENT_PATH = cwd();
const files = await readdir(CURRENT_PATH, {
recursive: false,
withFileTypes: true
});
const getIcon = (entry) => {
if (entry.isDirectory()) return "📁";
else if (entry.isFile()) return "📄";
else return "❓";
}
console.log(styleText("magenta", `El contenido de la carpeta`), ":");
console.log(CURRENT_PATH);
files.forEach((entry) => {
const icon = getIcon(entry);
const { name } = entry;
console.log(styleText("yellow", "- "), `${icon} ${name}`);
});
$ node index.js
El contenido de la carpeta: /home/manz/node-examples/fs-promises
- 📄 index.js
- 📄 jsconfig.json
- 📁 node_modules
- 📄 package.json
- 📄 pnpm-lock.yaml
- 📁 scripts
Al final del código, observa que hacemos un forEach
de files
obteniendo un icono y un nombre, extraído de cada entrada de readdir()
. Observa que el método getIcon()
utiliza métodos como .isDirectory()
o .isFile()
para saber si es un fichero o una carpeta. Con .name
obtenemos el nombre del fichero y con .path
obtenemos la ruta, entre otras cosas.
El método lstat()
Si necesitamos más información de un fichero o carpeta, podemos utilizar el método lstat()
. Por ejemplo, podemos obtener el tamaño del fichero con .size
o la fecha de modificación con .mtime
. En este fragmento de código, obtenemos esa información en la constante stat
, y los mostramos por pantalla en forma de columna:
import { cwd } from "node:process";
import { readdir, lstat } from "node:fs/promises";
import { styleText } from "node:util";
const CURRENT_PATH = cwd();
const files = await readdir(CURRENT_PATH, { recursive: false, withFileTypes: true });
console.log(styleText("magenta", `El contenido de la carpeta`), `: ${CURRENT_PATH}`);
const RTF = new Intl.RelativeTimeFormat("es-ES");
files.forEach(async (entry) => {
const stat = await lstat(`${entry.path}/${entry.name}`);
const sizes = [20, 30, 15];
const colors = ["white", "yellow", "green"];
const columns = [entry.name, stat.mtime.toISOString(), stat.size + " bytes"];
const line = [];
columns.forEach((column, index) => {
line.push(styleText(colors[index], column.padStart(sizes[index], " ")));
});
console.log(...line);
});`
El contenido de la carpeta : /home/manz/node-examples/fs-promises
index.js 2024-06-25T19:14:52.614Z 800 bytes
jsconfig.json 2024-06-25T12:51:32.470Z 3 bytes
node_modules 2024-06-25T12:50:16.020Z 4096 bytes
package.json 2024-06-25T12:50:16.020Z 240 bytes
pnpm-lock.yaml 2024-06-25T12:50:16.020Z 93 bytes
scripts 2024-06-25T16:36:37.346Z 4096 bytes
Otros métodos interesantes
Existen muchos otros métodos que pueden resultar interesantes, relacionados con el sistema de ficheros y carpetas. Por ejemplo, aquí algunos:
Método | Descripción |
---|---|
access() | Comprueba si tenemos permiso sobre ese fichero o carpeta. |
appendFile() | Añade información a un fichero que ya existe o inexistente. |
chmod() | Cambia los permisos de un fichero. |
chown() | Cambia el propietario de un fichero. |
cp() | Copia un fichero a una ruta específica. |
glob() | Busca los archivos que coincidan con un patrón dado. |
link() | Crea un enlace simbólico a un fichero o carpeta existente desde otra ruta. |
mkdir() | Crea una carpeta nueva. |
realpath() | Devuelve la ruta real de un fichero, generalmente de un enlace simbólico. |
rmdir() | Elimina una carpeta. |
rm() | Elimina ficheros o carpetas/directorios. |
unlink() | Elimina un fichero. |
watch() | Vigila cambios en ficheros o carpetas. |