Dos preguntas que debemos hacernos al hacer tales operaciones son:
- ¿Cuál es la cantidad de memoria utilizada para realizarlo?
- ¿El consumo de memoria aumenta drásticamente con el tamaño del archivo?
Soluciones como require('fs').readFileSync()
carga todo el archivo en la memoria. Eso significa que la cantidad de memoria requerida para realizar operaciones será casi equivalente al tamaño del archivo. Deberíamos evitarlos para algo más grande que50mbs
Podemos rastrear fácilmente la cantidad de memoria utilizada por una función colocando estas líneas de código después de la invocación de la función:
const used = process.memoryUsage().heapUsed / 1024 / 1024;
console.log(
`The script uses approximately ${Math.round(used * 100) / 100} MB`
);
En este momento la mejor manera de leer las líneas particulares de un archivo de gran tamaño está utilizando el nodo de readline . La documentación tiene ejemplos asombrosos .
Aunque no necesitamos ningún módulo de terceros para hacerlo. Pero, si está escribiendo un código de empresa, debe manejar muchos casos extremos. Tuve que escribir un módulo muy liviano llamado Apick File Storage para manejar todos esos casos .
Módulo Apick File Storage: https://www.npmjs.com/package/apickfs
Documentación: https://github.com/apickjs/apickFS#readme
Archivo de ejemplo: https://1drv.ms/t/s!AtkMCsWInsSZiGptXYAFjalXOpUx
Ejemplo: instalar módulo
npm i apickfs
// import module
const apickFileStorage = require('apickfs');
//invoke readByLineNumbers() method
apickFileStorage
.readByLineNumbers(path.join(__dirname), 'big.txt', [163845])
.then(d => {
console.log(d);
})
.catch(e => {
console.log(e);
});
Este método se probó con éxito con archivos densos de hasta 4 GB.
big.text es un archivo de texto denso con 163.845 líneas y es de 124 Mb. La secuencia de comandos para leer 10 líneas diferentes de este archivo utiliza aproximadamente solo 4,63 MB de memoria solamente. Y analiza JSON válido para objetos o matrices de forma gratuita. 🥳 Impresionante !!
Podemos leer una sola línea del archivo o cientos de líneas del archivo con muy poco consumo de memoria.
fs.readSync()
. Puede leer octetos binarios en un búfer, pero no hay una manera fácil de tratar con caracteres UTF-8 o UTF-16 parciales sin inspeccionar el búfer antes de traducirlo a cadenas de JavaScript y buscar EOL. ElBuffer()
tipo no tiene un conjunto de funciones tan rico para operar en sus instancias como las cadenas nativas, pero las cadenas nativas no pueden contener datos binarios. Me parece que la falta de una forma integrada de leer líneas de texto de archivos arbitrarios es una brecha real en node.js.