2012-02-06 20 views
65

Ho bisogno di passare un file di testo nel terminale e quindi leggere i dati da esso, come posso fare questo?Leggere un file di testo utilizzando Node.js?

node server.js file.txt 

Come si passa nel percorso dal terminale, come si legge sull'altro lato?

+0

Se vi trovate l'aggiunta di ulteriori opzioni sulla riga di comando, è possibile usare [Optimist] (https://github.com/substack/node-optimist). – Jess

+0

http://stackoverflow.com/questions/6156501/read-a-file-one-line-at-a-time-in-node-js?rq=1 mostra un altro modo di leggere un file di testo –

risposta

111

Si vorrà utilizzare l'array process.argv per accedere agli argomenti della riga di comando per ottenere il nome file e FileSystem module (fs) per leggere il file. Per esempio:

// 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) 
}); 

Per rompere che verso il basso un po 'per voi process.argv avrà solitamente la lunghezza di due, la voce zeroth essere l'interprete "nodo" e il primo è lo script che il nodo è attualmente in esecuzione, oggetti dopo che sono stati passato sulla riga di comando. Una volta che hai estratto un nome da argv, puoi usare le funzioni del filesystem per leggere il file e fare quello che vuoi con il suo contenuto. utilizzo del campione sarebbe simile a questa:

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

[Edit] Come @wtfcoder cita, utilizzando il metodo del "fs.readFile()" potrebbe non essere la migliore idea perché sarà tamponare l'intero contenuto del file prima di cedere a la funzione di callback. Questo buffering potrebbe potenzialmente utilizzare molta memoria ma, cosa più importante, non sfrutta una delle funzionalità principali di node.js: I/O asincrono e event.

Il modo "nodo" per elaborare un file di grandi dimensioni (o qualsiasi file, in realtà) sarebbe utilizzare fs.read() ed elaborare ogni blocco disponibile come è disponibile dal sistema operativo. Tuttavia, la lettura del file in quanto tale richiede di eseguire la propria (eventualmente) analisi/elaborazione incrementale del file e una certa quantità di buffering potrebbe essere inevitabile.

+0

Impressionante, grazie così tanto, molto utile. Come potrei dividere questi dati per linea? – fancy

+5

@fancy: prova 'var lines = data.split (/ \ r? \ N /);', quindi l'array "linee" avrà ciascuna linea. – maerics

+0

bello, sì l'ho fatto prima che tornassi a controllare, grazie ancora !! – fancy

20

IMHO, fs.readFile() deve essere evitato perché carica TUTTO il file in memoria e non richiamerà la richiamata fino a quando non è stato letto tutto il file.

Il modo più semplice per leggere un file di testo è leggerlo riga per riga. Vi consiglio 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(); 

Per strutture dati complesse come .properties o file JSON è necessario utilizzare un parser (internamente dovrebbe anche utilizzare un lettore di buffer).

+6

Grazie per aver sottolineato questa tecnica. Hai ragione che questo potrebbe essere il modo migliore, ma ho pensato che fosse leggermente confuso nel contesto di questa domanda, che credo stia facendo domande su un caso d'uso poco impegnativo. Come indicato sopra, se si tratta di un file di piccole dimensioni passato a uno strumento da riga di comando, non c'è motivo di non usare 'fs.readFile()' o 'fs.readFileSync()'. Deve essere un file enorme per provocare un'attesa notevole. Un file di configurazione JSON come package.json è probabilmente inferiore a 1 kb, quindi puoi semplicemente 'fs.readFile()' e 'JSON.parse()' it. –

+0

BufferedReader potrebbe aver cambiato la propria firma. Ho dovuto sostituire BufferedReader con BufferedReader, DataReader, dove BufferedReader era il modulo. Vedere https://github.com/Gagle/Node-BufferedReader – bnieland

+6

Vedo che BufferedReader è ora deprecato. –

1

È possibile utilizzare readstream e pipe per leggere il file riga per riga senza leggere tutti i file in memoria una volta.

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.'); 
    }) 
); 
1

Sto pubblicando un esempio completo che finalmente ho funzionato. Qui sto leggendo in un file rooms/rooms.txt da uno 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); 
}); 
Problemi correlati