はい、それを行う方法は複数ありますが、標準的または最も効率的または最も簡潔な方法が必要です。私が知っている回答を追加し、何が一番上に浸透するかを確認します。
明確にするために、問題はファイルの内容を文字列に読み取る最善の方法です。回答ごとに 1 つのソリューション。
これはどう:
use File::Slurp;
my $text = read_file($filename);
ETA: File-Slurp の Bug #83126: encoding(UTF-8) のセキュリティ ホールに注意してください。File::Slurperを使用することをお勧めします(免責事項: 私が書きました)。
use File::Slurper 'read_text';
my $text = read_text($filename);
またはPath::Tiny :
use Path::Tiny;
path($filename)->slurp_utf8;
do
ローカライズするブロックでこれを行うのが好きな@ARGV
ので、ひし形演算子を使用してファイル マジックを実行できます。
my $contents = do { local(@ARGV, $/) = $file; <> };
これをもう少し堅牢にする必要がある場合は、これを簡単にサブルーチンに変えることができます。
あらゆる種類の特殊なケースを処理する本当に堅牢なものが必要な場合は、File::Slurpを使用してください。使用しない場合でも、ソースを見て、対処する必要がある奇抜な状況をすべて確認してください。 File::Slurpには、解決策がないように見える大きなセキュリティ上の問題があります。これの一部は、エンコーディングを適切に処理できないことです。私の簡単な答えでさえ、その問題があります。エンコーディングを処理する必要がある場合 (デフォルトですべてを UTF-8 にするわけではないため)、これは次のように展開されます。
my $contents = do {
open my $fh, '<:encoding(UTF-8)', $file or die '...';
local $/;
<$fh>;
};
ファイルを変更する必要がない場合は、File::Mapを使用できる場合があります。
File::Slurp (これが最善の方法です) を書く際に、Uri Guttman は多くの研究を行い、どの方法が最も効率的かを調べました。彼は発見したことをここに書き留め、情報 File::Slurp に組み込みました。
open(my $f, '<', $filename) or die "OPENING $filename: $!\n";
$string = do { local($/); <$f> };
close($f);
考慮すべき事項 (特に他のソリューションと比較した場合):
だから私は得る:
my $contents = do {
local $/;
open my $fh, $filename or die "Can't open $filename: $!";
<$fh>
};
私は、実際に魔法を使うとき以外は、魔法があまり好きではありません。偽装する代わりに、 open 呼び出しを直接使用してみませんか? それはそれほど手間がかからず、明示的です。(真の魔法 <> は、特に "-" を処理する場合、完全にエミュレートするにははるかに手間がかかりますが、とにかくここでは使用しません。)
文字列の mmap (メモリ マッピング) は、次の場合に役立ちます。
#!/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);
更新: 2012 年 5 月
Sys::MmapをFile::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;
これは高速でも、プラットフォームに依存せず、本当に邪悪でもありませんが、短いです (Larry Wall のコードでこれを見たことがあります ;-):
my $contents = `cat $file`;
子供たち、家でそれをしないでください;-)。
{
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;
Perl6 :: Slurpの概要を参照してください。これは非常に柔軟性があり、通常、ほとんど労力をかけずに正しいことを実行します。
ワンライナーの場合、通常、 (ファイルに null バイトが含まれていない場合) perl にファイル全体を一度に読み取らせるために、-0
スイッチ( を使用) を使用できます。-n
perl -n0e 'print "content is in $_\n"' filename
バイナリ ファイルの場合は、次を使用できます-0777
。
perl -n0777e 'print length' filename
read や sysread について誰も何も言わなかったので、簡単で速い方法を次に示します。
my $string;
{
open my $fh, '<', $file or die "Can't open $file: $!";
read $fh, $string, -s $file; # or sysread
close $fh;
}
これは、最も一般的な方法の優れた比較です。
http://poundcomment.wordpress.com/2009/08/02/perl-read-entire-file/
それを行うための最悪の方法の候補!(コメントを参照してください。)
open(F, $filename) or die "OPENING $filename: $!\n";
@lines = <F>;
close(F);
$string = join('', @lines);
特別なレコード区切り変数を調整する$/
undef $/;
open FH, '<', $filename or die "$!\n";
my $contents = <FH>;
close FH;