Добавить JSON в файл, используя потоки узлов - PullRequest
0 голосов
/ 05 февраля 2019

Исходя из того, что я прочитал здесь , я использую fs.createWriteStream для записи некоторого JSON в файл.Я обрабатываю данные порциями по 50. Итак, в начале скрипта я открываю свой strea и затем использую функцию для его передачи вместе с некоторым JSON, который довольно хорошо работает для записи.

const myStream = fs.createWriteStream(
  path.join(RESULTS_DIR, `my-file.json`),
  {
    flags: 'a'
  }
)


function appendJsonToFile(stream, jsonToAppend) {
  return new Promise((resolve, reject) => {
    try {
      stream.write(JSON.stringify(jsonToAppend, null, 2)
      resolve('STREAM_WRITE_SUCCESS')
    } catch (streamError) {
      reject('STREAM_WRITE_FAILURE', streamError)
    }
  })
}

appendJsonToFile(myStream, someJson)

Однако, поскольку каждый фрагмент данных, который должен быть записан, представляет собой массив объектов, структура, которую я в конечном итоге получу в своем файле, будет выглядеть следующим образом:

[
    {
        "data": "test data 1",
    },
        {
        "data": "test data 2",
    }
][
    {
        "data": "test data 3",
    },
        {
        "data": "test data 4",
    }
]

Как я могу добавить эти фрагменты данныхчтобы результат был правильно отформатирован в формате JSON, а не просто в виде серии массивов?

1 Ответ

0 голосов
/ 06 февраля 2019

Если файл всегда отформатирован так, как вы сказали выше, вам нужно сделать три вещи:

  1. Узнать текущую длину файла и вычесть 2 символа (\n],так как в конце нет новой строки),
  2. Удалите первый символ JSON, который вы сохраняете,
  3. Сохраните файл в режиме r+ и start
  4. Завершать поток после каждого сохранения.

Вот ссылка на опции createWriteStream .

Теперь другой момент - пункт 4 делает это довольно неэффективным и ставит под сомнениеВся идея, если потоковая передача должна быть использована здесь.Я думаю, что это имеет смысл, но вопрос здесь в том, нужен ли вам файл для чтения между записями - если нет, то вы должны использовать transform stream в середине и добавить флэш между файлами и послевся работа выполнена (beforeExit), вы просто заканчиваете поток.

Вы можете сделать это по определению, но я являюсь автором фреймворка под названием scramjet , который делает эти случаи очень полезнымипроще:

const myStream = new scramjet.DataStream();

const file = path.join(RESULTS_DIR, `my-file.json`)
const start = fs.statSync(file).size - 2;

myStream
    .flatten()
    .toJSONArray()
    .shift(1)
    .pipe(fs.createWriteStream(
        file,
        {flags: 'r+', start}
    ));

function appendJsonToFile(stream, jsonToAppend) {
    return new Promise((resolve, reject) => {
        try {
            stream.write(jsonToAppend)
            resolve('STREAM_WRITE_SUCCESS')
        } catch (streamError) {
            reject('STREAM_WRITE_FAILURE', streamError)
        }
    })
}

appendJsonToFile(myStream, someJson)

process.on('beforeExit', myStream.end());

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

...