2016-09-14 40 views
1

J'essaie d'utiliser la méthode splitby dans highland.js pour extraire les données entre les délimiteurs de début et de fin.lire un fichier volumineux et une méthode splitby

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

Je peux lire le fichier dans un flux comme celui-ci:

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

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

Cependant, je ne peux pas sembler travailler sur la façon de traiter le fichier et extraire les données dont j'ai besoin.

Répondre

1

Il y a vraiment trois préoccupations ici.

  1. La lecture des données de contenu à partir de fichiers
  2. les morceaux Extraction
  3. délimités Obtenir les données résultant du flux

D'abord, vous devez lire le contenu de chaque fichier. Notez que readFile enveloppé va émettre Buffers, pas Strings. Pour extraire des morceaux, vous devez convertir le contenu de chaque fichier en String. Je suppose que les fichiers sont codés comme utf-8.

Ensuite, vous devez séparer les données du reste du texte. Je suppose que vous ne souhaitez que des morceaux entre les délimiteurs de début et de fin, sans délimiteurs eux-mêmes ou tout ce qui pourrait être en dehors des délimiteurs, par exemple:

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

devrait se traduire par:

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

Pour obtenir ce résultat j'utilise l'expression régulière avec deux groupes non-concordants pour les délimiteurs et un groupe correspondant pour les données. D'abord, j'extrais les morceaux délimités, puis enlève les délimiteurs. Cela peut ne pas être très efficace, mais devrait faire le travail.

Notez que le rappel de flatMap retournera un tableau de chaînes. L'utilisation de map entraînerait ici un flux de tableaux - un pour chaque fichier. Ce que nous voulons, c'est un seul flux de chaînes. C'est pourquoi flatMap `est utilisé ici.

Enfin, vous devez faire circuler le flux et extraire les données. Pour ce faire, vous devez appeler une méthode consommatrice sur le flux. Dans cet exemple, j'utilise toArray. Le rappel fourni à cette méthode sera appelé avec un tableau contenant tous les éléments du flux - dans ce cas, tous vos blocs de données.

est ici la chose dans son intégralité:

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 
)