Сохранить вывод csv-parse в переменную - PullRequest
0 голосов
/ 26 октября 2018

Я новичок в использовании csv-parse, и этот пример из github проекта делает то, что мне нужно, с одним исключением. Вместо вывода через console.log я хочу хранить данные в переменной. Я попытался присвоить строку fs переменной, а затем вернуть data вместо того, чтобы регистрировать ее, но это просто вернуло целую кучу вещей, которые я не понимал. Конечная цель - импортировать файл CSV в SQLite.

var fs = require('fs');
var parse = require('..');

var parser = parse({delimiter: ';'}, function(err, data){
  console.log(data);
});

fs.createReadStream(__dirname+'/fs_read.csv').pipe(parser);

Вот что я пробовал:

const fs = require("fs");
const parse = require("./node_modules/csv-parse");

const sqlite3 = require("sqlite3");
// const db = new sqlite3.Database("testing.sqlite");

let parser = parse({delimiter: ","}, (err, data) => {
    // console.log(data);
    return data;
});

const output = fs.createReadStream(__dirname + "/users.csv").pipe(parser);
console.log(output);

1 Ответ

0 голосов
/ 26 октября 2018

Этот вопрос предполагает путаницу в отношении API асинхронной потоковой передачи и, по-видимому, задает как минимум три вещи.

  1. Как мне получить output, чтобы содержать массив массивов, представляющихпроанализировал данные CSV?

То, что output никогда не будет существовать на верхнем уровне, как надеются вы (и многие другие программисты), из-за того, как работают асинхронные API.Все данные, собранные аккуратно в одном месте, могут существовать только в функции обратного вызова.Следующая лучшая вещь синтаксически это const output = await somePromiseOfOutput(), но это может произойти только в async function и только если мы переключимся с потоков на обещания.Это все возможно, и я упоминаю об этом, чтобы вы могли проверить это позже самостоятельно.Я предполагаю, что вы хотите придерживаться потоков.

Массив, состоящий из всех строк, может существовать только после чтения всего потока.Вот почему все строки доступны только в авторском примере «Stream API» только в обратном вызове .on('end', ...).Если вы хотите что-то сделать со всеми присутствующими строками одновременно, вам нужно будет сделать это в конце обратного вызова.

С https://csv.js.org/parse/api/ обратите внимание, что автор:

  1. использует обратный вызов on для чтения, чтобы поместить отдельные записи в ранее пустой массив, определенный с внешним именем output.
  2. использует обратный вызов on для сообщения об ошибках
  3. использует обратный вызов on end для сравнения всех накопленных записей в выводе с ожидаемым результатом

... const output = [] ... parser.on('readable', function(){ let record while (record = parser.read()) { output.push(record) } }) // Catch any error parser.on('error', function(err){ console.error(err.message) }) // When we are done, test that the parsed output matched what expected parser.on('end', function(){ assert.deepEqual( output, [ [ 'root','x','0','0','root','/root','/bin/bash' ], [ 'someone','x','1022','1022','','/home/someone','/bin/bash' ] ] ) })

Что касается цели взаимодействия с sqlite, это по сути создание настраиваемой конечной точки потоковой передачи.

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

Затем вы просто соединяете вызовы по конвейерукак

fs.createReadStream(__dirname+'/fs_read.csv') .pipe(parser) .pipe(your_writable_stream)

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

Реализация такого настраиваемого потока записи может быть затрудненаи оставлено в качестве упражнения для читателя.Будет проще, если синтаксический анализатор выдает строку, а затем средство записи может быть написано для обработки отдельных строк.Удостоверьтесь, что вы можете как-то замечать ошибки и выдавать соответствующие исключения, иначе вы будете прокляты с неполными результатами и без предупреждения или причины.

Хакерским способом было бы заменить console.log(data) в let parser = ... настраиваемой функцией writeRowToSqlite(data), которую вам все равно придется написать для реализации пользовательского потока.Из-за асинхронных проблем с API, использование return data не дает ничего полезного.Конечно, как вы видели, данные не помещаются в выходную переменную.


Относительно того, почему output в вашей измененной публикации не содержит данных ...

К сожалению, как вы обнаружили, это обычно неправильно:

const output = fs.createReadStream(__dirname + "/users.csv").pipe(parser); console.log(output);

Здесь переменная output будет ReadableStream , которая не совпадает с данными, содержащимися в читаемом потоке.Проще говоря, это как когда у вас есть файл в вашей файловой системе, и вы можете получить все виды системной информации о файле, но доступ к содержимому в файле осуществляется через другой вызов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...