¿Leer un archivo de texto con Node.js?

124

Necesito pasar un archivo de texto en la terminal y luego leer los datos, ¿cómo puedo hacer esto?

node server.js file.txt

¿Cómo paso en la ruta desde la terminal, cómo leo eso en el otro lado?

lujoso
fuente
Si se encuentra agregando más opciones en la línea de comando, puede usar Optimist .
Jess
stackoverflow.com/questions/6156501/… muestra otra forma de leer un archivo de texto
Marc Durdin

Respuestas:

172

Querrá usar la process.argvmatriz para acceder a los argumentos de la línea de comandos para obtener el nombre del archivo y el módulo FileSystem (fs) para leer el archivo. Por ejemplo:

// Make sure we got a filename on the command line.
if (process.argv.length < 3) {
  console.log('Usage: node ' + process.argv[1] + ' FILENAME');
  process.exit(1);
}
// Read the file and print its contents.
var fs = require('fs')
  , filename = process.argv[2];
fs.readFile(filename, 'utf8', function(err, data) {
  if (err) throw err;
  console.log('OK: ' + filename);
  console.log(data)
});

Para desglosarlo un poco, por lo process.argvgeneral tendrá una longitud dos, el elemento cero es el intérprete del "nodo" y el primero es el script que el nodo está ejecutando actualmente, los elementos posteriores se pasaron en la línea de comandos. Una vez que haya extraído un nombre de archivo de argv, puede usar las funciones del sistema de archivos para leer el archivo y hacer lo que quiera con su contenido. El uso de muestra se vería así:

$ node ./cat.js file.txt
OK: file.txt
This is file.txt!

[Editar] Como menciona @wtfcoder, usar el fs.readFile()método " " podría no ser la mejor idea porque almacenará en búfer todo el contenido del archivo antes de cederlo a la función de devolución de llamada. Este almacenamiento en búfer podría usar una gran cantidad de memoria pero, lo que es más importante, no aprovecha una de las características principales de node.js: E / S asíncrona y con eventos.

La forma de "nodo" para procesar un archivo grande (o cualquier archivo, en realidad) sería usar fs.read()y procesar cada fragmento disponible tal como está disponible en el sistema operativo. Sin embargo, leer el archivo como tal requiere que realice su propio (posiblemente) análisis / procesamiento incremental del archivo y una cierta cantidad de almacenamiento en búfer podría ser inevitable.

maerics
fuente
Impresionante, muchas gracias, muy útil. ¿Cómo podría dividir estos datos por línea?
elegante
10
@fancy: intente var lines = data.split(/\r?\n/);, entonces la matriz "líneas" tendrá cada línea.
maerics
1
Esto no es una buena idea si el archivo de texto es grande, ya que todo se leerá en la memoria, si procesa, digamos, un archivo CSV de 1000 MB, mire fs.createFilestream, deberá tener cuidado con la división de líneas, ya que los fragmentos de datos no caerá (en la mayoría de los casos) en los límites de la línea (algunas personas ya han encontrado soluciones - google)
Mâtt Frëëman
1
@wtfcoder: sí, muy buen punto. Mi intención era simplemente demostrar el simple caso de leer un archivo nombrado en la línea de comandos; Obviamente, hay muchas sutilezas (especialmente el desempeño) que están más allá del alcance de esta pregunta.
maerics
Publiqué una solución a una pregunta similar para analizar un archivo muy grande, usando una secuencia, sincrónica. ver: stackoverflow.com/questions/16010915/…
Gerard
35

Use fs con node.

var fs = require('fs');

try {  
    var data = fs.readFileSync('file.txt', 'utf8');
    console.log(data.toString());    
} catch(e) {
    console.log('Error:', e.stack);
}
Ronald
fuente
Tenga en cuenta que esta es la versión sincrónica .
Rich Werden
@RichWerden, ¿qué quiere decir con "sincrónico" en este contexto?
Json
1
En Node, cuando algo es "sincrónico", detiene / bloquea el sistema para que no haga nada más. Supongamos que tiene un servidor web de nodo: si entra cualquier otra solicitud mientras ocurre lo anterior, el servidor no responderá / no podrá responder porque está ocupado leyendo el archivo.
Rich Werden
27

En mi humilde opinión, fs.readFile()debería evitarse porque carga TODO el archivo en la memoria y no llamará a la devolución de llamada hasta que se haya leído todo el archivo.

La forma más sencilla de leer un archivo de texto es leerlo línea por línea. Recomiendo un BufferedReader :

new BufferedReader ("file", { encoding: "utf8" })
    .on ("error", function (error){
        console.log ("error: " + error);
    })
    .on ("line", function (line){
        console.log ("line: " + line);
    })
    .on ("end", function (){
        console.log ("EOF");
    })
    .read ();

Para estructuras de datos complejas como .properties o archivos json, necesita usar un analizador (internamente también debe usar un lector en búfer).

Gabriel Llamas
fuente
7
Gracias por señalar esta técnica. Tiene razón en que esta puede ser la mejor manera, pero pensé que era un poco confuso en el contexto de esta pregunta, que creo que se refiere a un caso de uso poco exigente. Como se señaló anteriormente, si es solo un archivo pequeño que se pasa a una herramienta de línea de comando, no hay razón para no usar fs.readFile()o fs.readFileSync(). Tiene que ser un archivo enorme para provocar una espera notable. Un archivo de configuración como JSON package.json es probable que sea menos de 1 kb, lo que sólo puede fs.readFile()y JSON.parse()él.
John Starr Dewar
1
BufferedReader puede haber cambiado su firma. Tuve que reemplazar BufferedReader con BufferedReader, DataReader, donde BufferedReader era el módulo. Ver github.com/Gagle/Node-BufferedReader
bnieland
13
Veo que BufferedReader ahora está en desuso.
Marc Rochkind
6

Puede usar readstream y pipe para leer el archivo línea por línea sin leer todo el archivo en la memoria una vez.

var fs = require('fs'),
    es = require('event-stream'),
    os = require('os');

var s = fs.createReadStream(path)
    .pipe(es.split())
    .pipe(es.mapSync(function(line) {
        //pause the readstream
        s.pause();
        console.log("line:", line);
        s.resume();
    })
    .on('error', function(err) {
        console.log('Error:', err);
    })
    .on('end', function() {
        console.log('Finish reading.');
    })
);
Kris Roofe
fuente
5

Estoy publicando un ejemplo completo que finalmente pude hacer funcionar. Aquí estoy leyendo en un archivo rooms/rooms.txtde un script.rooms/rooms.js

var fs = require('fs');
var path = require('path');
var readStream = fs.createReadStream(path.join(__dirname, '../rooms') + '/rooms.txt', 'utf8');
let data = ''
readStream.on('data', function(chunk) {
    data += chunk;
}).on('end', function() {
    console.log(data);
});
iamnotsam
fuente