Чтение большого файла и метод splitby

Я пытаюсь использовать splitby метод в highland.js извлечь данные между начальным и конечным разделителями.

        -----BEGIN DATA-----
        MIIEzDCCArSgAwIBAgIVCugKYzMN5ra8zPWxYE8pUU9SxjYSMA0GCSqGSIb3DQEB
        CwUAMHAxCzAJBgNVBAYTAkdCMRUwEwYDVQQIDAxXYXJ3aWNrc2hpcmUxEDAOBgNV
        BAcMB1dhcndpY2sxEDAOBgNVBAoMB0VudHJ1c3QxETAPBgNVBAsMCFBLSSBURUFN
        -----END DATA-----
        -----BEGIN DATA-----
        MIIETzCCAjegAwIBAgIVBShP2Mx74DZEyNKwYZZPGntRmSWnMA0GCSqGSIb3DQEB
        DQUAMHIxCzAJBgNVBAYTAkdCMRUwEwYDVQQIDAxXYXJ3aWNrc2hpcmUxEDAOBgNV
        BAcMB1dhcndpY2sxDDAKBgNVBAoMA0lCTTERMA8GA1UECwwIUEtJIFRFQU0xGTAX
        5/62
        -----END DATA-----

Я могу прочитать файл в поток, как это:

        const readFile = _.wrapCallback(fs.readFile);
        stream = _(files).map(readFile).parallel(2);

        const blob = _(stream).splitBy('-----BEGIN DATA-----')

Тем не менее, я не могу понять, как обработать файл и извлечь нужные мне данные.

1 ответ

Здесь действительно три проблемы.

  1. Чтение данных содержимого из файлов
  2. Извлечение разделенных кусков
  3. Получение результирующих данных из потока

Сначала вам нужно прочитать содержимое каждого файла. Обратите внимание, что завернутый readFile будет излучать Buffersне Strings, Чтобы извлечь куски, вам нужно преобразовать содержимое каждого файла в String, Я предполагаю, что файлы закодированы как utf-8,

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

-----BEGIN DATA-----
MIIEzDCCArSgAwIBAgIVCugKYzMN5ra8zPWxYE8pUU9SxjYSMA0GCSqGSIb3DQEB
CwUAMHAxCzAJBgNVBAYTAkdCMRUwEwYDVQQIDAxXYXJ3aWNrc2hpcmUxEDAOBgNV
BAcMB1dhcndpY2sxEDAOBgNVBAoMB0VudHJ1c3QxETAPBgNVBAsMCFBLSSBURUFN
-----END DATA-----
junky junk junk
-----BEGIN DATA-----
MIIETzCCAjegAwIBAgIVBShP2Mx74DZEyNKwYZZPGntRmSWnMA0GCSqGSIb3DQEB
DQUAMHIxCzAJBgNVBAYTAkdCMRUwEwYDVQQIDAxXYXJ3aWNrc2hpcmUxEDAOBgNV
BAcMB1dhcndpY2sxDDAKBgNVBAoMA0lCTTERMA8GA1UECwwIUEtJIFRFQU0xGTAX
5/62
-----END DATA-----

должно привести к:

[ '\nMIIEzDCCArSgAwIBAgIVCugKYzMN5ra8zPWxYE8pUU9SxjYSMA0GCSqGSIb3DQEB\nCwUAMHAxCzAJBgNVBAYTAkdCMRUwEwYDVQQIDAxXYXJ3aWNrc2hpcmUxEDAOBgNV\nBAcMB1dhcndpY2sxEDAOBgNVBAoMB0VudHJ1c3QxETAPBgNVBAsMCFBLSSBURUFN\n'
, '\nMIIETzCCAjegAwIBAgIVBShP2Mx74DZEyNKwYZZPGntRmSWnMA0GCSqGSIb3DQEB\nDQUAMHIxCzAJBgNVBAYTAkdCMRUwEwYDVQQIDAxXYXJ3aWNrc2hpcmUxEDAOBgNV\nBAcMB1dhcndpY2sxDDAKBgNVBAoMA0lCTTERMA8GA1UECwwIUEtJIFRFQU0xGTAX\n5/62\n'
]

Чтобы получить этот результат, я использую регулярное выражение с двумя несоответствующими группами для разделителей и подходящей группой для данных. Сначала я извлекаю разделенные части, а затем удаляю разделители. Это может быть не очень эффективно, но должно делать свою работу.

Обратите внимание, что обратный вызов flatMap вернет массив строк. С помощью map здесь бы получился поток массивов - по одному на каждый файл. То, что мы хотим, это один поток строк. Вот почему flatMap`используется здесь.

Наконец, вам нужно запустить поток и извлечь из него данные. Для этого вам нужно вызвать метод потребления в потоке. В этом примере я использую toArray. Обратный вызов, предоставленный этому методу, будет вызываться с массивом, содержащим все элементы потока - в этом случае все ваши блоки данных.

Вот вещь в целом:

const Stream = require("highland")
const FS = require("fs")

const files = [ "./input-1.txt", "./input-2.txt"  ]
const readFile = Stream.wrapCallback(FS.readFile);

const pattern = /(?:-----BEGIN DATA-----)((.|\n)+?)(?:-----END DATA-----)/gm

Stream(files)
  // 1. Read contents
  .map(readFile)
  .parallel(2)
  .invoke("toString", ["utf-8"])
  // 2. Process contents to extract data
  .flatMap((content) =>
    content
      // get an array of chunks (including delimiters)
      .match(pattern)
      // remove the delimiters from each chunk, leaving only the data
      .map((chunk) => chunk.replace(pattern, "$1")))
  // 3. Get the resulting data out of the stream
  .toArray((chunks) => 
    console.log(chunks) // will print an array of data chunks
  )
Другие вопросы по тегам