54

はい、それを行う方法は複数ありますが、標準的または最も効率的または最も簡潔な方法が必要です。私が知っている回答を追加し、何が一番上に浸透するかを確認します。

明確にするために、問題はファイルの内容を文字列に読み取る最善の方法です。回答ごとに 1 つのソリューション。

4

16 に答える 16

75

これはどう:

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;
于 2008-10-15T21:59:42.997 に答える
47

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を使用できる場合があります。

于 2008-10-15T22:30:49.767 に答える
35

File::Slurp (これが最善の方法です) を書く際に、Uri Guttman は多くの研究を行い、どの方法が最も効率的かを調べました。彼は発見したことをここに書き留め、情報 File::Slurp に組み込みました。

于 2008-10-18T08:35:58.437 に答える
24
open(my $f, '<', $filename) or die "OPENING $filename: $!\n";
$string = do { local($/); <$f> };
close($f);
于 2008-10-15T21:59:40.110 に答える
11

考慮すべき事項 (特に他のソリューションと比較した場合):

  1. レキシカルファイルハンドル
  2. 範囲を縮小
  3. 魔法を減らす

だから私は得る:

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

私は、実際に魔法を使うとき以外は、魔法があまり好きではありません。偽装する代わりに、 open 呼び出しを直接使用してみませんか? それはそれほど手間がかからず、明示的です。(真の魔法 <> は、特に "-" を処理する場合、完全にエミュレートするにははるかに手間がかかりますが、とにかくここでは使用しません。)

于 2008-10-15T22:38:38.770 に答える
10

文字列の mmap (メモリ マッピング) は、次の場合に役立ちます。

  • メモリにロードしたくない非常に大きな文字列がある
  • やみくもに高速な初期化が必要です (アクセス時に段階的な I/O を取得します)
  • 文字列へのランダム アクセスまたは遅延アクセスを行います。
  • 文字列を更新したいかもしれませんが、それを拡張するか、文字を置き換えるだけです:
#!/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::MmapFile::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);
于 2008-10-16T04:17:13.063 に答える
8
use Path::Class;
file('/some/path')->slurp;
于 2008-12-08T03:30:05.273 に答える
7

これは高速でも、プラットフォームに依存せず、本当に邪悪でもありませんが、短いです (Larry Wall のコードでこれを見たことがあります ;-):

 my $contents = `cat $file`;

子供たち、家でそれをしないでください;-)。

于 2008-10-16T06:44:44.030 に答える
7
{
  open F, $filename or die "Can't read $filename: $!";
  local $/;  # enable slurp mode, locally.
  $file = <F>;
  close F;
}
于 2008-10-15T21:59:55.227 に答える
6
use IO::All;

# read into a string (scalar context)
$contents = io($filename)->slurp;

# read all lines an array (array context)
@lines = io($filename)->slurp;
于 2011-08-10T20:09:04.453 に答える
4

Perl6 :: Slurpの概要を参照してください。これは非常に柔軟性があり、通常、ほとんど労力をかけずに正しいことを実行します。

于 2008-10-15T22:19:39.120 に答える
3

ワンライナーの場合、通常、 (ファイルに null バイトが含まれていない場合) perl にファイル全体を一度に読み取らせるために-0スイッチ( を使用) を使用できます。-n

perl -n0e 'print "content is in $_\n"' filename

バイナリ ファイルの場合は、次を使用できます-0777

perl -n0777e 'print length' filename
于 2014-10-28T12:36:29.417 に答える
3

read や sysread について誰も何も言わなかったので、簡単で速い方法を次に示します。

my $string;
{
    open my $fh, '<', $file or die "Can't open $file: $!";
    read $fh, $string, -s $file;   # or sysread
    close $fh;
}
于 2012-04-11T13:05:13.063 に答える
3

これは、最も一般的な方法の優れた比較です。

http://poundcomment.wordpress.com/2009/08/02/perl-read-entire-file/

于 2009-11-18T05:33:15.910 に答える
1

それを行うための最悪の方法の候補!(コメントを参照してください。)

open(F, $filename) or die "OPENING $filename: $!\n";
@lines = <F>;
close(F);
$string = join('', @lines);
于 2008-10-15T22:01:10.390 に答える
1

特別なレコード区切り変数を調整する$/

undef $/;
open FH, '<', $filename or die "$!\n";
my $contents = <FH>;
close FH;
于 2015-05-28T22:35:14.773 に答える