Oui, Il y a plus d'une façon de le faire Mais il doit y avoir une manière canonique ou la plus efficace ou la plus concise. Je vais ajouter des réponses que je connais et vois ce qui percolate au sommet.
Pour être clair, la question est la meilleure de lire le contenu d'un fichier dans une chaîne. Une solution par réponse.
Que dis-tu de ça:
use File::Slurp;
my $text = read_file($filename);
ETA: Remarque Bug # 83126 pour File-Slurp: trou de sécurité avec codage (UTF-8) . Je recommande maintenant d'utiliser Fichier :: Slurper (Disclaimer: Je l'ai écrit), aussi parce qu'il a de meilleures valeur par défaut autour des codages:
use File::Slurper 'read_text';
my $text = read_text($filename);
ou chemin :: minuscule :
use Path::Tiny;
path($filename)->Slurp_utf8;
J'aime faire cela avec un bloc do
block dans lequel je localise @ARGV
Donc, je peux utiliser l'opérateur de diamants pour faire le fichier magique pour moi.
my $contents = do { local(@ARGV, $/) = $file; <> };
Si vous avez besoin que cela soit un peu plus robuste, vous pouvez facilement le transformer en sous-programme.
Si vous avez besoin de quelque chose de vraiment robuste qui gère toutes sortes de cas spéciaux, utilisez fichier :: slurp . Même si vous n'allez pas l'utiliser, jetez un coup d'œil à la source pour voir toutes les situations loufoques qu'il doit gérer.fichier :: slurp a un gros problème de sécurité qui ne cherche pas à avoir une solution. Une partie de ceci est son défaillance de gérer correctement les codages. Même ma réponse rapide a ce problème. Si vous avez besoin de gérer le codage (peut-être parce que vous ne faites pas tout ce que UTF-8 par défaut), cela se développe à:
my $contents = do {
open my $fh, '<:encoding(UTF-8)', $file or die '...';
local $/;
<$fh>;
};
Si vous n'avez pas besoin de modifier le fichier, vous pourrez peut-être utiliser Fichier :: map .
En écrivant fichier :: slurp (qui est le meilleur moyen), Uri Guttman a fait beaucoup de recherches sur les nombreuses façons de la réduction et qui est la plus efficace. Il a écrit ses conclusions ici et les a incorporées Fichier d'information :: Slurp.
open(my $f, '<', $filename) or die "OPENING $filename: $!\n";
$string = do { local($/); <$f> };
close($f);
Choses à penser (surtout par rapport aux autres solutions):
Donc, je reçois:
my $contents = do {
local $/;
open my $fh, $filename or die "Can't open $filename: $!";
<$fh>
};
Je ne suis pas un grand fan de magie <> sauf en utilisant la magie <>. Au lieu de le simuler, pourquoi ne pas simplement utiliser l'appel ouvert directement? Ce n'est pas beaucoup plus de travail et est explicite. (Vraie magie <>, surtout lors de la manipulation "-", est beaucoup plus de travail pour imiter parfaitement, mais nous ne l'utilisons pas ici de toute façon.)
mMAP (mappage de mémoire) des chaînes peut être utile lorsque vous:
#!/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);
Mise à jour: Mai 2012
Les éléments suivants doivent être assez bien équivalents après avoir remplacé SYS :: MMAP avec Fichier :: map
#!/usr/bin/Perl
use warnings; use strict;
use File::Map qw{map_file};
map_file(my $str => '/tmp/words', '+<');
print substr($str, 100, 20);
use Path::Class;
file('/some/path')->Slurp;
{
open F, $filename or die "Can't read $filename: $!";
local $/; # enable Slurp mode, locally.
$file = <F>;
close F;
}
use IO::All;
# read into a string (scalar context)
$contents = io($filename)->Slurp;
# read all lines an array (array context)
@lines = io($filename)->Slurp;
Voir le résumé de Perl6 :: slurp qui est incroyablement flexible et fait généralement la bonne chose avec très peu d'effort.
Pour des doublures, vous pouvez généralement utiliser le -0
commutateur (avec -n
) Pour rendre Perl lire l'ensemble du fichier à la fois (si le fichier ne contient pas d'octets nuls):
Perl -n0e 'print "content is in $_\n"' filename
Si c'est un fichier binaire, vous pouvez utiliser -0777
:
Perl -n0777e 'print length' filename
Voici une belle comparaison des moyens les plus populaires de le faire:
http://poundComment.wordpress.com/2009/08/02/perl-read-entiper-file/
Candidat pour la pire façon de le faire! (Voir commentaire.)
open(F, $filename) or die "OPENING $filename: $!\n";
@lines = <F>;
close(F);
$string = join('', @lines);
Ajustez la variable de séparateur de record spécial $/
undef $/;
open FH, '<', $filename or die "$!\n";
my $contents = <FH>;
close FH;