Domanda Qual è il modo migliore per borseggiare un file in una stringa in Perl?


Sì, C'è più di un modo per farlo ma ci deve essere un modo canonico o più efficiente o più conciso. Aggiungerò le risposte che conosco e vedremo cosa percolerà fino in cima.

Per essere chiari, la domanda è il modo migliore per leggere il contenuto di un file in una stringa. Una soluzione per risposta.


46
2017-10-15 21:59


origine


risposte:


Cosa ne pensi di questo:

use File::Slurp;
my $text = read_file($filename);

ETA: nota Bug # 83126 per File-Slurp: buco di sicurezza con codifica (UTF-8). Ora consiglio di usare File :: Slurper (disclaimer: l'ho scritto), anche perché ha delle migliori impostazioni predefinite attorno alle codifiche:

use File::Slurper 'read_text';
my $text = read_text($filename);

o Percorso :: Piccolo:

use Path::Tiny;
path($filename)->slurp_utf8;

70
2017-10-15 22:30



Mi piace farlo con a do blocco in cui mi trovo @ARGV quindi posso usare l'operatore diamante per fare il file magico per me.

 my $contents = do { local(@ARGV, $/) = $file; <> };

Se hai bisogno che questo sia un po 'più robusto, puoi facilmente trasformarlo in una subroutine.

Se hai bisogno di qualcosa di veramente robusto che gestisca tutti i tipi di casi speciali, usa File :: Slurp. Anche se non hai intenzione di usarlo, dai un'occhiata alla fonte per vedere tutte le strane situazioni che deve gestire.  File :: Slurp ha un grande problema di sicurezza quello non sembra avere una soluzione. Parte di questo è il suo fallimento nel gestire correttamente le codifiche. Anche la mia risposta veloce ha quel problema. Se hai bisogno di gestire la codifica (forse perché non fai tutto per default in UTF-8), questo si espande a:

my $contents = do {
    open my $fh, '<:encoding(UTF-8)', $file or die '...';
    local $/;
    <$fh>;
    };

Se non hai bisogno di cambiare il file, potresti essere in grado di usarlo File :: Mappa.


44
2017-10-18 08:35



Per iscritto File :: Slurp (che è il modo migliore), Uri Guttman ha fatto molte ricerche nei molti modi di fare lo slurping e che è più efficiente. Ha scritto i suoi risultati qui e li ha incorporati informazioni File :: Slurp.


35
2017-10-15 22:38



open(my $f, '<', $filename) or die "OPENING $filename: $!\n";
$string = do { local($/); <$f> };
close($f);

20
2017-10-16 04:17



Cose a cui pensare (soprattutto se confrontati con altre soluzioni):

  1. Filehandles lessicali
  2. Riduci l'ambito
  3. Riduci la magia

Quindi ottengo:

my $contents = do {
  local $/;
  open my $fh, $filename or die "Can't open $filename: $!";
  <$fh>
};

Io non sono un grande fan della magia, tranne quando effettivamente uso la magia <>. Invece di fingere, perché non usare semplicemente la chiamata aperta direttamente? Non è molto più lavoro ed è esplicito. (La vera magia <>, specialmente quando si maneggia "-", è molto più lavoro da emulare perfettamente, ma non lo stiamo comunque usando qui.)


11
2017-10-15 21:59



mmap (Memory mapping) delle stringhe può essere utile quando:

  •  Hanno stringhe molto grandi, che non vuoi caricare nella memoria
  •  Vuoi un'inizializzazione ciecamente veloce (ottieni accesso I / O graduale)
  •  Avere accesso casuale o pigro alla stringa.
  •  Può voler aggiornare la stringa, ma la sta solo estendendo o sostituendo i caratteri:
#!/usr/bin/perl
use warnings; use strict;

use IO::File;
use Sys::Mmap;

sub sip {

    my $file_name = shift;
    my $fh;

    open ($fh, '+<', $file_name)
        or die "Unable to open $file_name: $!";

    my $str;

    mmap($str, 0, PROT_READ|PROT_WRITE, MAP_SHARED, $fh)
      or die "mmap failed: $!";

    return $str;
}

my $str = sip('/tmp/words');

print substr($str, 100,20);

Aggiornamento: maggio 2012

Il seguente dovrebbe essere abbastanza equivalente, dopo la sostituzione Sys :: mmap con File :: Mappa

#!/usr/bin/perl
use warnings; use strict;

use File::Map qw{map_file};

map_file(my $str => '/tmp/words', '+<');

print substr($str, 100, 20);

10
2017-10-15 22:19



use Path::Class;
file('/some/path')->slurp;

8
2017-10-16 06:44