Читать файл по одной строке в node.js? - PullRequest
500 голосов
/ 27 мая 2011

Я пытаюсь прочитать большой файл по одной строке за раз.Я нашел вопрос по Quora , который касался предмета, но мне не хватает некоторых связей, чтобы все это сошлось воедино.

 var Lazy=require("lazy");
 new Lazy(process.stdin)
     .lines
     .forEach(
          function(line) { 
              console.log(line.toString()); 
          }
 );
 process.stdin.resume();

Бит, который я хотел бы выяснитьЭто то, как я могу читать по одной строке за раз из файла вместо STDIN, как в этом примере.

Я пытался:

 fs.open('./VeryBigFile.csv', 'r', '0666', Process);

 function Process(err, fd) {
    if (err) throw err;
    // DO lazy read 
 }

, но это не работает.Я знаю, что в крайнем случае я мог бы вернуться к использованию чего-то вроде PHP, но я хотел бы выяснить это.

Не думаю, что другой ответ будет работать, так как файл намного больше, чем у сервера, на котором он запущен, есть память.

Ответы [ 27 ]

694 голосов
/ 16 сентября 2015

Начиная с Node.js v0.12 и начиная с Node.js v4.0.0, существует стабильный readline основной модуль. Вот самый простой способ чтения строк из файла без каких-либо внешних модулей:

var lineReader = require('readline').createInterface({
  input: require('fs').createReadStream('file.in')
});

lineReader.on('line', function (line) {
  console.log('Line from file:', line);
});

Последняя строка читается правильно (начиная с Node v0.12 или новее), даже если нет окончательного \n.

ОБНОВЛЕНИЕ : этот пример был добавлен в официальную документацию API Node .

157 голосов
/ 21 марта 2013

Для такой простой операции не должно быть никакой зависимости от сторонних модулей.Иди спокойно.

var fs = require('fs'),
    readline = require('readline');

var rd = readline.createInterface({
    input: fs.createReadStream('/path/to/file'),
    output: process.stdout,
    console: false
});

rd.on('line', function(line) {
    console.log(line);
});
63 голосов
/ 27 мая 2011

Вам не нужно open файл, но вместо этого вам нужно создать ReadStream.

fs.createReadStream

Затем передатьэтот поток в Lazy

35 голосов
/ 13 апреля 2012

есть очень хороший модуль для чтения файла построчно, он называется line-reader

, просто напишите:

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

lineReader.eachLine('file.txt', function(line, last) {
  console.log(line);
  // do whatever you want with line...
  if(last){
    // or check if it's the last one
  }
});

Вы даже можете перебрать файл с помощью интерфейса в стиле java, если вам нужен больший контроль:

lineReader.open('file.txt', function(reader) {
  if (reader.hasNextLine()) {
    reader.nextLine(function(line) {
      console.log(line);
    });
  }
});
25 голосов
/ 27 июня 2013
require('fs').readFileSync('file.txt', 'utf-8').split(/\r?\n/).forEach(function(line){
  console.log(line);
})
20 голосов
/ 10 апреля 2014

Старая тема, но это работает:

var rl = readline.createInterface({
      input : fs.createReadStream('/path/file.txt'),
      output: process.stdout,
      terminal: false
})
rl.on('line',function(line){
     console.log(line) //or parse line
})

Simple. Нет необходимости во внешнем модуле.

18 голосов
/ 28 августа 2012

Вы всегда можете свернуть свой собственный читатель строки. Я пока что не тестировал этот фрагмент, но он правильно разбивает входящий поток фрагментов на строки без завершающего '\ n'

var last = "";

process.stdin.on('data', function(chunk) {
    var lines, i;

    lines = (last+chunk).split("\n");
    for(i = 0; i < lines.length - 1; i++) {
        console.log("line: " + lines[i]);
    }
    last = lines[i];
});

process.stdin.on('end', function() {
    console.log("line: " + last);
});

process.stdin.resume();

Я придумал это, когда работал над сценарием быстрого анализа журнала, который должен был накапливать данные во время анализа журнала, и я чувствовал, что было бы неплохо попробовать сделать это с помощью js и node вместо использования perl или bash.

В любом случае, я чувствую, что небольшие сценарии nodejs должны быть автономными и не полагаться на сторонние модули, поэтому после прочтения всех ответов на этот вопрос, каждый из которых использует различные модули для обработки разборов строк, может быть решение для 13 SLOC-нативных nodejs. интерес.

12 голосов
/ 24 августа 2011

С операторским модулем :

var carrier = require('carrier');

process.stdin.resume();
carrier.carry(process.stdin, function(line) {
    console.log('got one line: ' + line);
});
8 голосов
/ 09 апреля 2012

Редактировать:

Использовать поток преобразования .


С BufferedReader вы можете читать строки.

new BufferedReader ("lorem ipsum", { 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 ();
8 голосов
/ 09 ноября 2011

Я закончил с огромной утечкой памяти, используя Lazy для чтения построчно при попытке затем обработать эти строки и записать их в другой поток из-за того, как работает сток / пауза / возобновление в узле (см .: http://elegantcode.com/2011/04/06/taking-baby-steps-with-node-js-pumping-data-between-streams/ (я люблю этого парня, кстати)).Я недостаточно внимательно посмотрел на Lazy, чтобы точно понять, почему, но я не мог приостановить свой поток чтения, чтобы обеспечить сток без выхода из Lazy.

Я написал код для обработки массивных csv-файлов в xml-документах., вы можете увидеть код здесь: https://github.com/j03m/node-csv2xml

Если вы запустите предыдущие ревизии с Ленивой линией, она утечет.Последняя версия вообще не имеет утечки, и вы, вероятно, можете использовать ее в качестве основы для считывателя / процессора.Хотя у меня там есть кое-что нестандартное.

Редактировать: Полагаю, я должен также отметить, что мой код с Lazy работал нормально, пока я не обнаружил, что пишу достаточно большие фрагменты XML, которые истощают / приостанавливают / возобновляют, поскольку это необходимо.Для небольших кусков это было хорошо.

...