Большой CSV в JSON / Объект в Node.js

Я пытаюсь сделать что-то, что кажется не только довольно простым для выполнения, но и достаточно общей задачей, чтобы для этого были доступны простые пакеты. Я хочу взять большой файл CSV (экспорт из таблицы реляционной базы данных) и преобразовать его в массив объектов JavaScript. Кроме того, я хотел бы экспортировать его в.json файл крепежа.

Пример CSV:

a,b,c,d
1,2,3,4
5,6,7,8
...

Желаемый JSON: я

[
{"a": 1,"b": 2,"c": 3,"d": 4},
{"a": 5,"b": 6,"c": 7,"d": 8},
...
]

Мы пробовали несколько узлов CSV-парсеры, стримеры, самопровозглашенные библиотеки CSV-to-JSON, но я могуКажется, я получаю желаемый результат или, если могу, он работает, только если файлы меньше. Мой файл имеет размер около 1 ГБ с ~ 40 м строк (что приведет к созданию 40 м объектов). Я ожидаю, что это потребует потоковой передачи ввода и / или вывода, чтобы избежать проблем с памятью.

Вот пакеты, которые ямы пробовали:

https://github.com/klaemo/csv-streamhttps://github.com/koles/ya-csvhttps://github.com/davidgtonge/stream-convert (работает, но это настолько медленно, что бесполезно, так как я часто изменяю набор данных. Потребовалось почти 3 часа для анализа файла csv 60 МБ)https://github.com/cgiffard/CSVtoJSON.jshttps://github.com/wdavidw/node-csv-parser (Безразлично»Кажется, он предназначен для преобразования CSV в другие форматы)https://github.com/voodootikigod/node-csvI»

Я использую узел 0.10.6 и хотел бы получить рекомендацию о том, как легко это сделать. Лучше катиться, но яя не уверен, с чего начать весь нодs потоковые функции, тем более что они изменили API в 0.10.x.

 Dogbert17 мая 2013 г., 22:42
Вы уверены, что не сделалине забудьте удалить некоторые скобки в "Желаемый JSON " раздел? не должен»не так ли?{"a": 1, "b": 2, "c": 3, "d": 4},
 neverfox17 мая 2013 г., 22:44
Ой, спасибо. Ред.

Ответы на вопрос(6)

который можно использовать в качестве библиотеки, инструментов командной строки или плагина веб-сервера.https://www.npmjs.org/package/csvtojson, Исходный код можно найти по адресу:https://github.com/Keyang/node-csvtojson

или установить из репозитория NPM:

npm install -g csvtojson

Он поддерживает любой размер данных CSV / тип поля / вложенный JSON и т. Д. Куча функций.

пример

var Converter=require("csvtojson").core.Converter;

var csvConverter=new Converter({constructResult:false, toArrayString:true}); // The constructResult parameter=false will turn off final result construction in memory for stream feature. toArrayString will stream out a normal JSON array object.

var readStream=require("fs").createReadStream("inputData.csv"); 

var writeStream=require("fs").createWriteStream("outpuData.json");

readStream.pipe(csvConverter).pipe(writeStream);

Вы также можете использовать его как инструмент Cli:

csvtojson myCSVFile.csv

чтобы обрабатывать большие файлы. Вот что вам нужно сделать. Это должно работать просто отлично.

npm i --save csv2json fs-extra // install the modules

const csv2json = require('csv2json');
const fs = require('fs-extra');

const source = fs.createReadStream(__dirname + '/data.csv');
const output = fs.createWriteStream(__dirname + '/result.json');
 source
   .pipe(csv2json())
   .pipe(output );

неплохо справляется с подобными задачами.

Следующее решение использует потоки, так как они выиграливзорвать вашу память

Установить зависимости
npm install through2 split2 --save
Код
import through2 from 'through2'
import split2 from 'split2'

fs.createReadStream('<yourfilepath>')
  // Read line by line
  .pipe(split2())
  // Parse CSV line
  .pipe(parseCSV()) 
  // Process your Records
  .pipe(processRecord()) 

const parseCSV = () => {
  let templateKeys = []
  let parseHeadline = true
  return through2.obj((data, enc, cb) => {
    if (parseHeadline) {
      templateKeys = data
        .toString()
        .split(';')
      parseHeadline = false
      return cb(null, null)
    }
    const entries = data
      .toString()
      .split(';')
    const obj = {}
    templateKeys.forEach((el, index) => {
      obj[el] = entries[index]
    })
    return cb(null, obj)
  })
}

const processRecord = () => {
  return through2.obj(function (data, enc, cb) {
    // Implement your own processing 
    // logic here e.g.:
    MyDB
      .insert(data)
      .then(() => cb())
      .catch(cb)
  })
}
</yourfilepath>

Для получения дополнительной информации по этой теме посетите Stefan Baumgartners отличноруководство по теме.

tojson.

Вот's код:

var Converter = require("csvtojson").Converter;
var converter = new Converter({});
converter.fromFile("sample.csv",function(err,result){
  var csvData = JSON.stringify
  ([
    {resultdata : result[0]},
    {resultdata : result[1]},
    {resultdata : result[2]},
    {resultdata : result[3]},
    {resultdata : result[4]}
  ]);
  csvData = JSON.parse(csvData);
  console.log(csvData);
});

или вы можете легко сделать это:

var Converter = require("csvtojson").Converter;
var converter = new Converter({});
converter.fromFile("sample.csv",function(err,result){ 
  console.log(result);
});

Вот's результат из 1-го кода:

[ { resultdata: 
     { 'Header 1': 'A_1',
       'Header 2': 'B_1',
       'Header 3': 'C_1',
       'Header 4': 'D_1',
       'Header 5': 'E_1' } },
  { resultdata: 
     { 'Header 1': 'A_2',
       'Header 2': 'B_2',
       'Header 3': 'C_2',
       'Header 4': 'D_2',
       'Header 5': 'E_2' } },
  { resultdata: 
     { 'Header 1': 'A_3',
       'Header 2': 'B_3',
       'Header 3': 'C_3',
       'Header 4': 'D_3',
       'Header 5': 'E_3' } },
  { resultdata: 
     { 'Header 1': 'A_4',
       'Header 2': 'B_4',
       'Header 3': 'C_4',
       'Header 4': 'D_4',
       'Header 5': 'E_4' } },
  { resultdata: 
     { 'Header 1': 'A_5',
       'Header 2': 'B_5',
       'Header 3': 'C_5',
       'Header 4': 'D_5',
       'Header 5': 'E_5' } } ]

Исходный код этого кода находится в:https://www.npmjs.com/package/csvtojson#installation

Я надеюсь, у вас есть идея.

Решение Вопроса

вы можете основывать свое решение наhttps://github.com/dominictarr/event-stream , Адаптированный пример из readme:

    var es = require('event-stream')
    es.pipeline(                         //connect streams together with `pipe`
      process.openStdin(),              //open stdin
      es.split(),                       //split stream to break on newlines
      es.map(function (data, callback) { //turn this async function into a stream
        callback(null
          , JSON.stringify(parseCSVLine(data)))  // deal with one line of CSV data
      }), 
      process.stdout
      )

После этого я ожидаю, что в каждой строке будет куча строковых объектов JSON. Затем его необходимо преобразовать в массив, который вы можете сделать и добавить, до конца каждой строки, удаляя ее на последней, а затем добавляя[ а также] в начало и конец файла.

parseCSVLine Функция должна быть настроена на присвоение значений CSV нужным свойствам объекта. Это может быть довольно легко сделано после прохождения первой строки файла.

Я заметил, что библиотека не тестировалась на 0.10 (по крайней мере, на Travis), так что будьте осторожны. Может быть, запуститьnpm test на источнике сами.

 neverfox17 мая 2013 г., 22:59
Благодарю. я пыталсяevent-stream но продолжайте терпеть неудачу, когда дело доходит доes.map, Я'Я буду продолжать это и, надеюсь, решить это.
 Myrne Stol17 мая 2013 г., 23:03
У меня нетЯ сам работал с Event-Stream. Может быть, посмотрите на тесты для примера кода?
 Evgeniy Generalov11 окт. 2017 г., 22:37
es.split () может быть недостаточно для разделения CSV по строкам. В соответствии сrfc-editor.org/rfc/rfc4180.txt символ новой строки может быть частью значения, если оно заключено в двойные кавычки.

scramjet

$ npm install --save scramjet

А потом

process.stdin.pipe(
    new (require("scramjet").StringStream)("utf-8")
)
    .CSVParse()
    .toJSONArray()
    .pipe(process.stdout)

Это приведет к тому, что вы описали в потоковом режиме.

Ваш ответ на вопрос