2015-02-26 12 views
8

Immagina di avere molti file di testo lunghi e devi solo estrarre i dati dalla prima riga di ognuno (senza leggere ulteriori contenuti). Qual è il modo migliore in Node JS per farlo?Qual è il modo più efficace per leggere solo la prima riga di un file in Node JS?

Grazie!

+1

è possibile chiamare il comando 'head' sui file dal nodo? utilizzare le funzionalità del file/sistema operativo per ciò che sono buoni per. :) – TZHX

+1

Il codice di cui ho bisogno fa parte di una libreria che può essere utilizzata su qualsiasi sistema operativo che supporta il nodo JS, quindi sarebbe meglio farlo utilizzando il nodo stesso. Se non sbaglio, 'head' non è disponibile su Windows, ad esempio. – Pensierinmusica

+0

devi sapere per quanto tempo quella prima riga è, ma puoi sovrascrivere e caricare il primo, ad esempio 5kb, e quindi dividere quel 5kb per linee, mantenendo solo il primo. usa fs.read() invece di fs.readFile(): http://nodejs.org/api/fs.html#fs_fs_read_fd_buffer_offset_length_position_callback – dandavis

risposta

6

ho finito per l'adozione di questa soluzione, che sembra la più performante che ho visto finora:

var fs = require('fs'); 
var Q = require('q'); 

function readFirstLine (path) { 
    return Q.promise(function (resolve, reject) { 
    var rs = fs.createReadStream(path, {encoding: 'utf8'}); 
    var acc = ''; 
    var pos = 0; 
    var index; 
    rs 
     .on('data', function (chunk) { 
     index = chunk.indexOf('\n'); 
     acc += chunk; 
     index !== -1 ? rs.close() : pos += chunk.length; 
     }) 
     .on('close', function() { 
     resolve(acc.slice(0, pos + index)); 
     }) 
     .on('error', function (err) { 
     reject(err); 
     }) 
    }); 
} 

ho creato un modulo NPM per comodità, denominato "firstline".

Grazie a @dandavis per il suggerimento di utilizzare String.prototype.slice()!

+0

interessante, quanto è grande ogni _chunk_? – dandavis

+0

@dandavis, 64 kb – Pensierinmusica

+1

grazie per il ritorno. sembra che ho bisogno di riadare la mia dimensione del buffer e cambiare il mio consiglio di std ... lo offrirei per la massima velocità (se questo è importante), sarebbe più veloce usare 'acc.slice (0, acc.indexOf (" \ n "))' sull'evento close invece di dividere l'intero 64kb +, o persino di passare in qualche modo l'indice dall'evento di dati (più la lunghezza di acc) per l'efficienza bare-metal. – dandavis

1

// Ecco qua;

var lineReader = require('line-reader'); 
var async = require('async'); 

exports.readManyFiles = function(files) { 
    async.map(files, 
     function(file, callback)) 
      lineReader.open(file, function(reader) { 
       if (reader.hasNextLine()) { 
       reader.nextLine(function(line) { 
        callback(null,line); 
       }); 
       } 
      }); 
     }, 
     function(err, allLines) { 
      //do whatever you want to with the lines 
     }) 
}