Я пытаюсь прочитать большой файл по одной строке за раз. Я нашел вопрос о 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, но я хотел бы выяснить это.
Я не думаю, что другой ответ будет работать, так как файл намного больше, чем у сервера, на котором он запущен, есть память.
javascript
node.js
file-io
lazy-evaluation
Алекс С
источник
источник
fs.readSync()
. Вы можете читать двоичные октеты в буфер, но нет простого способа справиться с частичными символами UTF-8 или UTF-16 без проверки буфера перед его преобразованием в строки JavaScript и сканированием на наличие EOL.Buffer()
Тип не имеет как богатый набор функций для работы на его экземплярах , как родные строки, но родные строки не могут содержать двоичные данные. Мне кажется, что отсутствие встроенного способа чтения текстовых строк из произвольных файловых дескрипторов является настоящим пробелом в node.js.if (line.length==1 && line[0] == 48) special(line);
node
документации по API github.com/nodejs/node/pull/4609Ответы:
Начиная с Node.js v0.12 и начиная с Node.js v4.0.0, существует стабильный основной модуль readline . Вот самый простой способ прочитать строки из файла без каких-либо внешних модулей:
Или в качестве альтернативы:
Последняя строка читается правильно (начиная с Node v0.12 или более поздней), даже если финальной версии нет
\n
.ОБНОВЛЕНИЕ : этот пример был добавлен к официальной документации Node API .
источник
rl.on('close', cb)
Для такой простой операции не должно быть никакой зависимости от сторонних модулей. Полегче.
источник
line
события происходят только после нажатия\n
, т. е. все альтернативы пропущены (см. unicode.org/reports/tr18/#Line_Boundaries ). # 2, данные после последнего\n
игнорируются (см. Stackoverflow.com/questions/18450197/… ). я бы назвал это решение опасным, потому что оно работает для 99% всех файлов и для 99% данных, но для остальных ничего не получается . всякий раз, когда вы это делаете,fs.writeFileSync( path, lines.join('\n'))
вы пишете файл, который будет читаться только частично вышеуказанным решением.readline
пакет ведет себя по- настоящему странным образом к опытному Unix / Linux программиста.rd.on("close", ..);
может использоваться как обратный вызов (происходит, когда все строки прочитаны)Вам не нужно
open
файл, но вместо этого вы должны создатьReadStream
.fs.createReadStream
Затем передайте этот поток
Lazy
источник
new lazy(fs.createReadStream('...')).lines.forEach(function(l) { /* ... */ }).join(function() { /* Done */ })
new lazy(...).lines.forEach(...).on('end', function() {...})
.on('end'...
после того.forEach(...)
, как на самом деле все выглядело так, как ожидалось, когда я связал событие первым .есть очень хороший модуль для чтения файла построчно, он называется line-reader
с этим вы просто пишете:
Вы можете даже перебрать файл с помощью интерфейса в стиле java, если вам нужно больше контроля:
источник
process/stdin
). По крайней мере, если это возможно, это, конечно, не очевидно из чтения кода и его попытки.readline
модуль ядра .function(reader)
иfunction(line)
должно быть:function(err,reader)
иfunction(err,line)
.line-reader
читает файл асинхронно. Синхронная альтернатива этомуline-reader-sync
источник
Обновление в 2019 году
Отличный пример уже опубликован в официальной документации Nodejs. Вот
Для этого требуется, чтобы на вашем компьютере была установлена последняя версия Nodejs. > 11,4
источник
await
s междуcreateInterface()
вызовом и началомfor await
цикла, вы таинственным образом потеряете строки с начала файла.createInterface()
немедленно начинает испускать строки за кулисами, и асинхронный итератор, неявно созданный с,const line of rl
не может начать прослушивать эти строки, пока он не будет создан.Старая тема, но это работает:
Просто. Нет необходимости во внешнем модуле.
источник
readline is not defined
илиfs is not defined
, добавьтеvar readline = require('readline');
и,var fs = require('fs');
чтобы заставить это работать. В противном случае сладкий, сладкий код. Спасибо.Вы всегда можете свернуть свой собственный читатель строки. Я пока не тестировал этот фрагмент, но он правильно разбивает входящий поток фрагментов на строки без завершающего '\ n'
Я придумал это, работая над сценарием быстрого анализа журнала, который должен был накапливать данные во время анализа журнала, и я чувствовал, что было бы неплохо попробовать сделать это, используя js и node вместо использования perl или bash.
В любом случае, я чувствую, что небольшие сценарии nodejs должны быть автономными и не полагаться на сторонние модули, поэтому после прочтения всех ответов на этот вопрос, каждый из которых использует различные модули для обработки разборов строк, может оказаться интересным решение 13 SLOC для нативных nodejs.
источник
stdin
... если я не пропустил что-нибудь.ReadStream
сfs.createReadStream('./myBigFile.csv')
и использовать его вместоstdin
readline
модуль ядра .С несущим модулем :
источник
var inStream = fs.createReadStream('input.txt', {flags:'r'});
Но ваш синтаксис чище, чем документированный метод использования .on ():carrier.carry(inStream).on('line', function(line) { ...
\r\n
и\n
символы конца строки. Если вам когда-нибудь потребуется иметь дело с тестовыми файлами в стиле MacOS, выпущенными до OS X, они используются,\r
и оператор не справится с этим. Удивительно, но в дикой природе еще существуют такие файлы. Возможно, вам также придется обрабатывать спецификацию Unicode (метку порядка байтов), это используется в начале текстовых файлов в сфере влияния MS Windows.readline
модуль ядра .Я закончил с огромной утечкой памяти, используя Lazy для чтения построчно при попытке затем обработать эти строки и записать их в другой поток из-за того, как работает сток / пауза / возобновление в узле (см .: http: // Elegantcode .com / 2011/04/06 / брать ребенка шаги с узлом js накачка данных между потоками / (я люблю этого парня, кстати)). Я не достаточно внимательно посмотрел на Lazy, чтобы понять, почему именно, но я не мог приостановить поток чтения, чтобы обеспечить сток без выхода Lazy.
Я написал код для обработки больших CSV-файлов в XML-документы, вы можете увидеть код здесь: https://github.com/j03m/node-csv2xml
Если вы запускаете предыдущие ревизии с ленивой линией, она просачивается. Последняя версия вообще не имеет утечки, и вы, вероятно, можете использовать ее как основу для считывателя / процессора. Хотя у меня есть кое-какие нестандартные вещи.
Изменить: Я думаю, я должен также отметить, что мой код с Lazy работал нормально, пока я не обнаружил, что пишу достаточно большие фрагменты XML, которые истощают / пауза / резюме, потому что это необходимо. Для небольших кусков это было хорошо.
источник
readline
основной модуль .Редактировать:
Используйте поток преобразования .
С BufferedReader вы можете читать строки.
источник
readline
основной модуль .После публикации моего исходного ответа я обнаружил, что split - это очень простой в использовании модуль узла для чтения строк в файле; Который также принимает необязательные параметры.
Не проверял на очень больших файлах. Дайте нам знать, если вы делаете.
источник
Я был разочарован отсутствием комплексного решения для этого, поэтому я собрал свою собственную попытку ( git / npm ). Вставленный в копию список функций:
НАЦИОНАЛЬНЫЕ ИНСТИТУТЫ ЗДРАВООХРАНЕНИЯ США? Вам решать :-)
источник
источник
data
в вызовеstream.on("data")
могуществе когда начинаются или заканчиваются только часть многобайтовыми UTF-8 символов , таких , как ,ა
которыйU+10D0
, состоит из трех байтовe1
83
90
readline
основной модуль .Я хотел решить эту же проблему, в основном то, что было бы в Perl:
Мой вариант использования был всего лишь автономным сценарием, а не сервером, поэтому синхронный был в порядке. Это были мои критерии:
Это проект для меня, чтобы почувствовать низкоуровневый код типа сценариев в node.js и решить, насколько он жизнеспособен в качестве замены для других языков сценариев, таких как Perl.
После удивительного усилия и нескольких неудачных попыток, это код, который я придумал. Это довольно быстро, но менее тривиально, чем я ожидал: (раскошелиться на GitHub)
Вероятно, это можно было убрать дальше, это было результатом проб и ошибок.
источник
В большинстве случаев этого должно быть достаточно:
источник
Читатель линии на основе генератора: https://github.com/neurosnap/gen-readlines
источник
Если вы хотите прочитать файл построчно и записать это в другом:
источник
У меня была та же проблема, и я предложил вышеупомянутое решение, похожее на других, но это aSync и может очень быстро читать большие файлы.
Надеется, что это помогает
источник
У меня есть небольшой модуль, который делает это хорошо и используется многими другими проектами. Npm readline Обратите внимание, что в узле v10 есть собственный модуль readline, поэтому я переиздал свой модуль как linebyline https://www.npmjs.com/package/ построчно
если вы не хотите использовать модуль, функция очень проста:
источник
Другое решение - запустить логику через последовательного исполнителя nsynjs . Он читает файл построчно, используя модуль readline узла, и не использует обещания или рекурсию, поэтому не собирается завершать работу с большими файлами. Вот как будет выглядеть код:
Код выше основан на этом экзамене: https://github.com/amaksr/nsynjs/blob/master/examples/node-readline/index.js
источник
При выполнении таких операций мы должны задать себе два вопроса:
Такие решения, как
require('fs').readFileSync()
загрузка всего файла в память. Это означает, что объем памяти, необходимый для выполнения операций, будет практически эквивалентен размеру файла. Мы должны избегать этого для чего-то большего, чем50mbs
Мы можем легко отследить объем памяти, используемый функцией, поместив эти строки кода после вызова функции:
Прямо сейчас лучший способ прочитать определенные строки из большого файла - использовать readline узла . В документации есть удивительные примеры .
Хотя нам не нужен какой-либо сторонний модуль для этого. Но, если вы пишете корпоративный код, вам придется обрабатывать множество крайних случаев. Мне пришлось написать очень легкий модуль Apick File Storage для обработки всех этих крайних случаев.
Модуль хранения файлов Apick: https://www.npmjs.com/package/apickfs Документация: https://github.com/apickjs/apickFS#readme
Файл примера: https://1drv.ms/t/s!AtkMCsWInsSZiGptXYAFjalXOpUx
Пример: установить модуль
Этот метод был успешно протестирован с плотными файлами до 4 ГБ.
big.text представляет собой плотный текстовый файл с 163 845 строками и объемом 124 Мб. Скрипт для чтения 10 различных строк из этого файла использует только 4,63 МБ памяти. И он анализирует действительный JSON для объектов или массивов бесплатно. !! Круто !!
Мы можем прочитать одну строку файла или сотни строк файла с очень небольшим потреблением памяти.
источник
я использую это:
используйте эту функцию в потоке и слушайте события линии, которые будут излучать.
gr-
источник
Хотя вам, вероятно, следует использовать
readline
модуль, как подсказывает главный ответ,readline
похоже, он ориентирован на интерфейсы командной строки, а не на чтение строк. Это также немного более непрозрачно в отношении буферизации. (Любой, кому нужен читатель, ориентированный на потоковую линию, вероятно, захочет настроить размер буфера). Модуль readline составляет ~ 1000 строк, а со статистикой и тестами - 34.Вот еще более короткая версия без статистики в 19 строк:
источник
источник
Я оборачиваю всю логику ежедневной обработки строк в виде модуля npm: line-kit https://www.npmjs.com/package/line-kit
источник
Я использую приведенный ниже код для чтения строк после того, как убедитесь, что это не каталог и его нет в списке файлов.
источник
Я просмотрел все приведенные выше ответы, все они используют стороннюю библиотеку для ее решения. Это простое решение в Node API. например
источник