Node.js: чтение текстового файла в массив. (Каждая строка - элемент в массиве.)
Я хотел бы прочитать очень, очень большой файл в массив JavaScript в node.js.
Итак, если файл выглядит так:
first line
two
three
...
...
У меня будет массив:
['first line','two','three', ... , ... ]
Функция будет выглядеть так:
var array = load(filename);
Поэтому идея погрузить все это как строку и затем расщепить ее неприемлема.
Ответы
Ответ 1
Если вы можете поместить окончательные данные в массив, не могли бы вы также поместить его в строку и разделить ее, как было предложено?
В любом случае, если вы хотите обработать файл по одной строке за раз, вы также можете попробовать что-то вроде этого:
var fs = require('fs');
function readLines(input, func) {
var remaining = '';
input.on('data', function(data) {
remaining += data;
var index = remaining.indexOf('\n');
while (index > -1) {
var line = remaining.substring(0, index);
remaining = remaining.substring(index + 1);
func(line);
index = remaining.indexOf('\n');
}
});
input.on('end', function() {
if (remaining.length > 0) {
func(remaining);
}
});
}
function func(data) {
console.log('Line: ' + data);
}
var input = fs.createReadStream('lines.txt');
readLines(input, func);
РЕДАКТИРОВАТЬ: (в ответ на комментарий от phopkins) Я думаю (по крайней мере, в более новых версиях) подстрока не копирует данные, а создает специальный объект SlicedString (с быстрым взглядом на исходный код v8). В любом случае, здесь есть модификация, которая позволяет избежать упомянутой подстроки (проверенной в файле на несколько мегабайт "Все работы и без игры делает Джека скучным мальчиком" ):
function readLines(input, func) {
var remaining = '';
input.on('data', function(data) {
remaining += data;
var index = remaining.indexOf('\n');
var last = 0;
while (index > -1) {
var line = remaining.substring(last, index);
last = index + 1;
func(line);
index = remaining.indexOf('\n', last);
}
remaining = remaining.substring(last);
});
input.on('end', function() {
if (remaining.length > 0) {
func(remaining);
}
});
}
Ответ 2
Синхронный:
var fs = require('fs');
var array = fs.readFileSync('file.txt').toString().split("\n");
for(i in array) {
console.log(array[i]);
}
Асинхронный:
var fs = require('fs');
fs.readFile('file.txt', function(err, data) {
if(err) throw err;
var array = data.toString().split("\n");
for(i in array) {
console.log(array[i]);
}
});
Ответ 3
Используя модуль Node.js readline.
var fs = require('fs');
var readline = require('readline');
var filename = process.argv[2];
readline.createInterface({
input: fs.createReadStream(filename),
terminal: false
}).on('line', function(line) {
console.log('Line: ' + line);
});
Ответ 4
используйте readline (документация). здесь пример чтения css файла, разбора значков и записи их в json
var results = [];
var rl = require('readline').createInterface({
input: require('fs').createReadStream('./assets/stylesheets/_icons.scss')
});
// for every new line, if it matches the regex, add it to an array
// this is ugly regex :)
rl.on('line', function (line) {
var re = /\.icon-icon.*:/;
var match;
if ((match = re.exec(line)) !== null) {
results.push(match[0].replace(".",'').replace(":",''));
}
});
// readline emits a close event when the file is read.
rl.on('close', function(){
var outputFilename = './icons.json';
fs.writeFile(outputFilename, JSON.stringify(results, null, 2), function(err) {
if(err) {
console.log(err);
} else {
console.log("JSON saved to " + outputFilename);
}
});
});
Ответ 5
С BufferedReader, но функция должна быть асинхронной:
var load = function (file, cb){
var lines = [];
new BufferedReader (file, { encoding: "utf8" })
.on ("error", function (error){
cb (error, null);
})
.on ("line", function (line){
lines.push (line);
})
.on ("end", function (){
cb (null, lines);
})
.read ();
};
load ("file", function (error, lines){
if (error) return console.log (error);
console.log (lines);
});
Ответ 6
file.lines
с пакетом JFile
Псевдо
var JFile=require('jfile');
var myF=new JFile("./data.txt");
myF.lines // ["first line","second line"] ....
Не забывайте, прежде чем:
npm install jfile --save
Ответ 7
Это вариация ответа выше на @mtomis.
Создает поток строк. Он испускает события "данные" и "конец", что позволяет обрабатывать конец потока.
var events = require('events');
var LineStream = function (input) {
var remaining = '';
input.on('data', function (data) {
remaining += data;
var index = remaining.indexOf('\n');
var last = 0;
while (index > -1) {
var line = remaining.substring(last, index);
last = index + 1;
this.emit('data', line);
index = remaining.indexOf('\n', last);
}
remaining = remaining.substring(last);
}.bind(this));
input.on('end', function() {
if (remaining.length > 0) {
this.emit('data', remaining);
}
this.emit('end');
}.bind(this));
}
LineStream.prototype = new events.EventEmitter;
Используйте его как оболочку:
var lineInput = new LineStream(input);
lineInput.on('data', function (line) {
// handle line
});
lineInput.on('end', function() {
// wrap it up
});
Ответ 8
Я просто хочу добавить @finbarr отличный ответ, небольшое исправление в асинхронном примере:
Асинхронный:
var fs = require('fs');
fs.readFile('file.txt', function(err, data) {
if(err) throw err;
var array = data.toString().split("\n");
for(i in array) {
console.log(array[i]);
}
done();
});
@MadPhysicist, done() - это то, что освобождает async. звоните.
Ответ 9
У меня была та же проблема, и я решил ее с модулем по очереди
https://www.npmjs.com/package/line-by-line
По крайней мере, для меня работает как шарм, как в синхронном, так и в асинхронном режиме.
Кроме того, проблема с линиями, заканчивающимися без завершения \n, может быть решена с помощью опции:
{ encoding: 'utf8', skipEmptyLines: false }
Синхронная обработка строк:
var LineByLineReader = require('line-by-line'),
lr = new LineByLineReader('big_file.txt');
lr.on('error', function (err) {
// 'err' contains error object
});
lr.on('line', function (line) {
// 'line' contains the current line without the trailing newline character.
});
lr.on('end', function () {
// All lines are read, file is closed now.
});
Ответ 10
Чтобы прочитать большой файл в массиве, вы можете читать строки за строкой или фрагментом блоком.
строка за строкой обратитесь к моему ответу здесь
var fs = require('fs'),
es = require('event-stream'),
var lines = [];
var s = fs.createReadStream('filepath')
.pipe(es.split())
.pipe(es.mapSync(function(line) {
//pause the readstream
s.pause();
lines.push(line);
s.resume();
})
.on('error', function(err) {
console.log('Error:', err);
})
.on('end', function() {
console.log('Finish reading.');
console.log(lines);
})
);
chunk by chunk относятся к этой статье
var offset = 0;
var chunkSize = 2048;
var chunkBuffer = new Buffer(chunkSize);
var fp = fs.openSync('filepath', 'r');
var bytesRead = 0;
while(bytesRead = fs.readSync(fp, chunkBuffer, 0, chunkSize, offset)) {
offset += bytesRead;
var str = chunkBuffer.slice(0, bytesRead).toString();
var arr = str.split('\n');
if(bytesRead = chunkSize) {
// the last item of the arr may be not a full line, leave it to the next chunk
offset -= arr.pop().length;
}
lines.push(arr);
}
console.log(lines);