Aiuta ad analizzare file di testo lunghi (3,5 ml di righe), riga per riga e memorizzazione dei dati, serve una strategia

3

Questa è una domanda sulla risoluzione di un particolare problema con cui sto lottando, sto analizzando una lunga lista di dati testuali, riga per riga per un'applicazione di business in PHP (script cron sulla CLI). Il file segue il formato:

    HD: Some text here {text here too}

    DC: A description here
    DC: the description continues here
    DC: and it ends here.

    DT: 2012-08-01

    HD: Next header here {supplemental text}

    ... this repeats over and over for a few hundred megs

Devo leggere ogni riga, analizzare l'HD: linea e afferrare il testo su questa linea. Quindi confronto questo testo con i dati memorizzati in un database. Quando viene trovata una corrispondenza, desidero quindi registrare le seguenti righe DC: che hanno avuto successo con l'HD corrispondente:.

Pseudo codice:

    while ( the_file_pointer_isnt_end_of_file) {
        line = getCurrentLineFromFile
        title = parseTitleFrom(line)
        matched = searchForMatchInDB(line)
        if ( matched ) {
            recordTheDCLines  // <- Best way to do this?
        }
    }

Il mio problema è che, poiché sto leggendo riga per riga, qual è il modo migliore per far scattare lo script per iniziare a salvare le linee DC, e poi quando sono finite salvarle nel database?

Ho una vaga idea, ma devo ancora implementarla correttamente. Mi piacerebbe sentire le idee della community \ suggerimenti!

Grazie.

    
posta Jarrod 08.12.2012 - 21:35
fonte

4 risposte

5

Separa il problema: uno script esplora e legge e inserisce le cose interessanti in una sorta di archivio dati. Il secondo script attinge dall'archivio dati ed elabora i record. Sospetto che sarà molto più veloce rispetto a farlo nello stesso script per nessun altro motivo che il secondo script in modo efficace multi-thread dell'applicazione.

    
risposta data 09.12.2012 - 00:03
fonte
2

Scrivi una due funzioni o una classe LineReader con le seguenti funzioni:

  • string GetNextLine (): legge la riga successiva dal file
  • string PeekLine (): ottiene la riga successiva dal file, ma non sposta il puntatore del file

(è possibile implementarlo facilmente con un buffer di riga costituito da una variabile di stringa che tiene una riga in anticipo, GetNextLine deve fare uso di tale buffer oltre a PeekLine).

Quindi l'implementazione di recordDCLines dovrebbe essere qualcosa come

 while(substr(PeekLine(),0,3)=="DC:")
 {
    line=GetNextLine();
    // process line, append it to a buffer
 }
 // here, store the found DC block

EDIT: qualche pseudo codice, non ho esperienza in PHP, ma spero che tu abbia un'idea generale:

 void OpenFile()
 {
     // do stuff here to open file
     // ...
     $nextline = getNextLineFromFile();
     $endoffile = false;
 }

 string GetNextLine()
 {
      if(isset($nextline))
      {
         $result=$nextline;
         if(!noMoreLinesAvailable())
             $nextline = getNextLineFromFile();
         else
             unset($nextline);
      } 
      else 
      {
         $endoffile=true;
         $result ="";
      }
      return $result;
 }

 string PeekLine()
 {
     return $nextline;
 }
    
risposta data 08.12.2012 - 23:40
fonte
1

Implementa una macchina di stato di base. Mentre stai leggendo le righe, nota l'ultimo 'comando' (dc, dt, ecc.). Quando ottieni un 'HD', fai le tue ricerche. Quando sei in uno stato DC, sai di accumulare il messaggio fino a quando l'elemento successivo non è una voce DC, a quel punto fai una scrittura.

    
risposta data 09.12.2012 - 06:02
fonte
0

Potresti considerare di scrivere un'estensione PHP in C o C ++ a tale scopo; potresti quindi utilizzare syscalls di basso livello, ma efficienti (ad es. mmap (2 , leggi (2) in un buffer di grandi dimensioni, readahead (2) , ecc ... )

Potresti anche delegare a un programma di supporto scritto in C.

    
risposta data 08.12.2012 - 23:53
fonte

Leggi altre domande sui tag