- Оригинальный адрес:Using Node.js to Read Really, Really Large Files (Pt 1)
- Оригинальный автор:Paige Niedringhaus
- Перевод с:Программа перевода самородков
- Постоянная ссылка на эту статью:GitHub.com/rare earth/gold-no…
- Переводчик:lucasleliane
- Корректор:sunui,Jane Liao
Чтение очень больших файлов с помощью Node.js (часть 1)
Этот пост в блоге имеет очень интересную точку вдохновения. На прошлой неделе кто-то опубликовал на моем канале Slack задачу по программированию, которую он получил, когда подавал заявку на роль разработчика в страховой компании.
Я был заинтригован этой задачей, которая требовала чтения большого количества файлов данных из Федеральной избирательной комиссии и отображения некоторых конкретных данных из этих файлов. Поскольку я ничего не делал с необработанными данными и всегда открыт для новых задач, я решил решить эту проблему с помощью Node.js, чтобы посмотреть, смогу ли я справиться с этим и повеселиться.
Ниже приведены четыре заданных вопроса, а также ссылки на наборы данных, которые эта программа должна проанализировать.
- Напишите программу, которая выводит общее количество строк в файле.
- Обратите внимание, что восьмой столбец содержит имя человека. Напишите программу для загрузки этих данных и создайте массив для хранения всех строк имен. Распечатайте 432-е и 43243-е имена.
- Обратите внимание, что пятый столбец содержит отформатированное время. Подсчитайте свои ежемесячные пожертвования и распечатайте результаты.
- Обратите внимание, что восьмой столбец содержит имя человека. Создайте массив для хранения каждого имени. Отметьте наиболее часто используемое имя в данных и сколько раз оно встречается.
Ссылка на данные:Woohoo. Поделитесь с .gov/files/black-…
Когда вы распаковываете папку, вы видите файл размером 2,55 ГБ..txt
Основной файл и папка, содержащая некоторые данные из основного файла (это то, что я использовал для тестирования своего решения перед запуском основного файла).
Не очень страшно, правда? кажется, работает. Итак, давайте посмотрим, как я этого добился.
Два нативных решения Node.js, которые я придумал
Обработка больших файлов не является чем-то новым для JavaScript, на самом деле среди основных функций Node.js есть множество стандартных решений для чтения и записи файлов.
Среди них наиболее прямымfs.readFile()
, этот метод прочитает весь файл в память, а затем выполнит операцию, как только Node закончит чтение, второй вариант —fs.createReadStream()
, этот метод обрабатывает ввод и вывод данных в виде потоков данных, подобно Python или Java.
Решение, которое я использую, и почему я его использую
Поскольку мое решение включает подсчет общего количества строк и анализ данных для каждой строки, чтобы получить имя и дату пожертвования, я выбираю второй метод:fs.createReadStream()
. Затем при циклическом просмотре файла я могу использоватьrl.on('line',...)
функция для получения необходимых данных из каждой строки файла.
Для меня это проще, чем читать весь файл в память, а затем читать его построчно.
Реализация кода Node.js CreateReadStream() и ReadFile()
Вот что я делаю с Node.jsfs.createReadStream()
Код реализации функции. Я разобью это ниже.
Первое, что мне нужно было сделать, это импортировать необходимые функции из Node.js:fs
(Файловая система),readline
,а такжеstream
. После их импорта я могу создатьinstream
иoutstream
тогда позвониreadLine.createInterface()
, они позволяют мне читать поток построчно и печатать из него данные.
Я также добавил некоторые переменные (и комментарии) для хранения различных данных:lineCount
,names
множество,donation
массивы и объекты, а такжеfirstNames
массив иdupeNames
объект. Вы сможете увидеть их в действии позже.
существуетrl.on('line',...)
Внутри функции я могу выполнить построчный анализ данных. Здесь я делаю для каждой строки потока данныхlineCount
увеличение . я использую джаваскриптsplit()
метод для анализа каждого имени и добавления его вnames
в массиве. Я бы дополнительно сократил каждое имя до первого имени, а в JavaScripttrim()
,includes()
а такжеsplit()
С помощью метода вычислите первую букву отчества и количество раз, когда это имя встречается. Затем я разделил год и время столбца времени, чтобы отформатировать его, чтобы он был более читабельным.YYYY-MM
отформатировать и добавить вdateDonationCount
в массиве.
существуетrl.on('close',...)
функции, я преобразовываю собранные данные в массив, а вconsole.log
Показать все мои данные пользователю с помощью .
Найдите 432-й и 43243-й индексыlineCount
иnames
Никаких дальнейших действий не требуется. Найти самые частые имена и ежемесячные пожертвования сложнее.
Для наиболее распространенных имен мне сначала нужно создать объект пары «ключ-значение» для хранения каждого имени (как ключа) и количество раз, которое это имя появляется (как значение), затем я использую функции ES6.Object.entries()
преобразовать его в массив. Тогда отсортировать этот массив и вывести максимальное значение очень просто.
Для получения количества пожертвований также требуется аналогичный объект ключ-значение, мы создаемlogDateElements()
мы можем использовать интерполяцию строк ES6 для отображения ключевого значения суммы ежемесячного пожертвования. Затем создайтеnew Map()
будетdateDonations
объекты преобразуются во вложенные массивы, и для каждого вызова элемента массиваlogDateElements()
функция. вызов! Не так просто, как я сначала думал.
По крайней мере, это сработало для файла размером 400 МБ, с которым я тестировал...
С использованиемfs.createReadStream()
После того, как метод выполнен, я возвращаюсь и пытаюсь использоватьfs.readFile()
реализовать мое решение и увидеть разницу. Ниже приведен код этого метода, но я не буду вдаваться здесь во все подробности. Этот код очень похож на первый фрагмент, за исключением того, что он выглядит более синхронным (если только вы не используетеfs.readFileSync()
метод, но не беспокойтесь, JavaScript выполнит этот код, как и любой другой асинхронный код).
Если вы хотите увидеть полную версию моего кода, вы можете найти ее по адресуздесьоказаться.
Первые результаты для Node.js
С моим решением я перехожу кreadFileStream.js
заменил путь к файлу этим чудовищным файлом размером 2,55 ГБ и посмотрел на мой сервер Node, потому чтоJavaScript heap out of memory
вылетел с ошибкой.
Получается, что хотя Node.js использует потоки для чтения и записи файлов, он все равно пытается сохранить все содержимое файла в памяти, что невозможно для размера файла. Узел может хранить до 1,5 ГБ за раз, но не может увеличиться.
Таким образом, ни одно из моих текущих решений не способно выполнить всю эту задачу.
Мне нужно новое решение. Решение на основе Node, способное обрабатывать большие наборы данных.
Новые решения для потоковой передачи данных
EventStream
— популярный модуль NPM с более чем 2 миллионами загрузок в неделю, который утверждает, что «облегчает создание и использование потоков».
С помощью документации EventStream я снова понял, как читать код построчно и делать это более дружественным к процессору способом.
Реализация кода EventStream
Это мой новый код, реализованный с помощью модуля EventStream NPM.
Самым большим изменением является команда pipe в начале файла — весь этот синтаксис, как предлагает документация EventStream, через.txt
в конце каждой строки файла\n
символ для разложения потока.
Единственное, что я изменил, это модифицированныйnames
результат. Я должен быть честным, потому что я пытался поместить 13 миллионов имен в массив, и ему все равно не хватило памяти. Я обошел это и просто собрал 432-е и 43243-е имена и добавил их в свой собственный массив. Не по какой-либо другой причине, я просто хотел проявить немного творчества.
Внедрение Node.js и EventStream: раунд 2
Хорошо, новое решение реализовано, и снова я запустил Node.js с файлом размером 2,55 ГБ и приложил все усилия, чтобы на этот раз все заработало. Посмотрим на результаты.
Это сработало!
в заключении
В конце концов, чистые возможности обработки файлов и больших данных Node.js немного далеки от того, что мне нужно, но с дополнительным модулем NPM, таким как EventStream, я смог анализировать огромные данные без сбоя сервера Node.
Оставайтесь с нами для этой серииВторая часть, я протестировал и сравнил производительность трех способов чтения данных в Node.js, чтобы увидеть, какой из них работает лучше, чем другой. Результаты становятся весьма впечатляющими, особенно по мере роста объема данных...
Спасибо за прочтение, надеюсь, эта статья помогла вам понять, как использовать Node.js для обработки больших объемов данных. Спасибо за ваши лайки и подписку!
Если вам понравилось читать это, вам также могут понравиться некоторые из моих других блогов:
- Postman vs. Insomnia: сравнение инструментов тестирования API
- Как использовать Eureka и Spring Cloud от Netflix для регистрации в сервисе
- Jib: Получите экспертные результаты Docker, не зная Docker
Цитируйте и продолжайте читать ресурсы:
- Документация Node.js, файловая система:nodejs.org/api/fs.html
- Документация Node.js, Readline:node будет .org/API/read forest…
- Github, прочитайте репозиторий файлов:GitHub.com/Hands11/FI…
- NPM, EventSream:уууу, эта лошадь plus.com/package/eve…
Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.
Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из ИнтернетаНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллекти другие поля, если вы хотите видеть больше качественных переводов, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.