La lettura di una specifica linea dal file di grandi dimensioni in Perl

C’è qualche veloce e memoria efficiente modo di leggere di specifiche linee di file di grandi dimensioni, senza caricarlo di memoria?

Ho scritto uno script in perl, che viene eseguito molte forcelle e mi piacerebbe loro di leggere le righe di un file.

Al momento Im utilizzando un comando esterno:

sub getFileLine {
    my ( $filePath, $lineWanted ) = @_;
    $SIG{PIPE} = '_IGNORE_';
    open( my $fh, '-|:utf8', "tail -q -n +$lineWanted \"$filePath\" | head -n 1" );
    my $line = <$fh>;
    close $fh;
    chomp( $line );
    return $line;
}

La sua veloce e funziona – ma forse c’è di più “Perl-ish” via, più veloce e più memoria efficiente come questo?

Come sapete, la creazione di una forchetta processo in Perl duplicati principale di memoria del processo: se il processo principale che utilizza la 10MB, la forcella usa almeno che molto.

Il mio obiettivo è quello di mantenere la forcella del processo (in modo principale processo fino a quando l’esecuzione di forcelle anche) l’utilizzo di memoria più basso possibile. Ecco perché io non voglio caricare tutto il file in memoria.

  • btw, è IGNORE, non _IGNORE_.
InformationsquelleAutor gib | 2011-12-18



3 Replies
  1. 17

    Prima di proseguire, è importante capire come fork opere. Quando si fork un processo, il sistema operativo utilizza copy-on-write semantica di condividere il grosso dei processi padre e figlio’ di memoria; solo la quantità di memoria che varia tra il genitore e il figlio devono essere separatamente assegnati.

    Per la lettura di una singola riga di un file in Perl, ecco un modo semplice:

    open my $fh, '<', $filePath or die "$filePath: $!";
    my $line;
    while( <$fh> ) {
        if( $. == $lineWanted ) { 
            $line = $_;
            last;
        }
    }

    Questo utilizza lo speciale $. variabile che contiene il numero di riga corrente filehandle.

  2. 4

    Dare un’occhiata a Tie::File core module.

    • Ho pensato Tie::File è la memoria-inefficiente. Non l’OP richiesta di utilizzo di memoria insufficiente?
    • in realtà è ragionevolmente efficace in termini di memoria; non memorizzare l’intero contenuto del file in memoria, solo un elenco di offset di ogni riga. Non è gratis (anche solo il scalari di tenere ogni offset prendere un po ‘ di spazio per riga), ma è di solito abbastanza buono per gestire multi-centinaia di megabyte di file con facilità.
    • Yup. Ho guardato la documentazione da allora (il commento è abbastanza vecchio ormai), e rende abbastanza chiaro che non è una memoria di porco.
  3. 0

    Non hai bisogno di forcella. Come si può immaginare, la lettura di una specifica linea di un file è un’operazione abbastanza comune che uno dei 20k moduli CPAN fa già.

    File::ReadBackwards è la memoria, efficiente e veloce.

Lascia un commento