46

注意してください - 私は、ファイルを開いたり読んだりする「正しい」方法、またはファイルを毎回開いたり読んだりする方法を探しているわけではありません。私は、ほとんどの人がどのような方法を使用しているかを知り、同時にいくつかの新しい方法を学ぶことに興味があります:)*

私の Perl プログラムで非常に一般的なコード ブロックは、ファイルを開いて読み書きすることです。私はこれを行う多くの方法を見てきましたが、このタスクを実行する際の私のスタイルは、何年にもわたって何度か変化しています。これを行うための最善の方法(最善の方法がある場合)は何ですか?

私は次のようなファイルを開いていました:

my $input_file = "/path/to/my/file";
open INPUT_FILE, "<$input_file"  || die "Can't open $input_file: $!\n";

しかし、エラートラップに問題があると思います。

括弧を追加すると、エラー トラップが修正されるようです。

open (INPUT_FILE, "<$input_file")  || die "Can't open $input_file: $!\n";

ファイルハンドルを変数に代入することもできるので、上記のように "INPUT_FILE" を使用する代わりに、$input_filehandle を使用することもできました。

ファイルを読み取る場合、ファイルが小さい場合、このようにグロビングに問題はありますか?

my @array = <INPUT_FILE>;

また

my $file_contents = join( "\n", <INPUT_FILE> );

または、次のように常にループする必要があります。

my @array;
while (<INPUT_FILE>) {
  push(@array, $_);
}

perl で物事を達成する方法がたくさんあることは知っていますが、ファイルを開いて読み込むための推奨/標準的な方法があるかどうか疑問に思っています。

4

12 に答える 12

59

普遍的な基準はありませんが、どちらかを好む理由があります。私の好みの形式はこれです:

open( my $input_fh, "<", $input_file ) || die "Can't open $input_file: $!";

理由は次のとおりです。

  • エラーをすぐに報告します。(必要に応じて、「die」を「warn」に置き換えてください。)
  • ファイルハンドルは参照カウントされるようになったため、使用しない場合は自動的に閉じられます。グローバル名INPUT_FILEHANDLEを使用する場合は、ファイルを手動で閉じる必要があります。そうしないと、プログラムが終了するまでファイルは開いたままになります。
  • 読み取りモードインジケータ「<」は$input_fileから分離されているため、読みやすさが向上します。

ファイルが小さく、すべての行が必要であることがわかっている場合は、以下が最適です。

my @lines = <$input_fh>;

すべての行を単一の文字列として処理する必要がある場合は、これを行うこともできます。

my $text = join('', <$input_fh>);

長いファイルの場合は、whileを使用して行を繰り返すか、readを使用します。

于 2008-11-25T20:55:46.977 に答える
15

ファイル全体を単一の文字列にしたい場合は、それを反復処理する必要はありません。

use strict;
use warnings;
use Carp;
use English qw( -no_match_vars );
my $data = q{};
{
   local $RS = undef; # This makes it just read the whole thing,
   my $fh;
   croak "Can't open $input_file: $!\n" if not open $fh, '<', $input_file;
   $data = <$fh>;
   croak 'Some Error During Close :/ ' if not close $fh;
}

上記は満足perlcritic --brutalしています。これは、「ベストプラクティス」をテストするための良い方法です:)。$input_fileここではまだ定義されていませんが、残りはコーシャです。

于 2008-11-25T21:00:24.267 に答える
14

どこにでも「または死ぬ」と書かなければならないことは私を狂わせます。ファイルを開くための私の好ましい方法は次のようになります。

use autodie;

open(my $image_fh, '<', $filename);

タイピングはごくわずかですが、注意すべき重要なことがたくさんあります。

  • 自動ダイプラグマを使用しています。つまり、問題が発生した場合、Perlのすべての組み込み関数が例外をスローします。コードを記述する必要がなくor die ...、人間が読める形式のわかりやすいエラーメッセージが生成され、字句スコープがあります。CPANから入手できます。

  • openの3つの引数バージョンを使用しています。<これは、、、、などの文字を含む面白いファイル名がある場合>でも|、Perlが正しいことを実行することを意味します。OSCONでのPerlセキュリティチュートリアルでは、2つの引数openを誤動作させるいくつかの方法を示しました。このチュートリアルのメモは、PerlTrainingAustraliaから無料でダウンロードできます

  • スカラーファイルハンドルを使用しています。これは、同じ名前の他の誰かのファイルハンドルを偶然に閉じることはないことを意味します。これは、パッケージファイルハンドルを使用する場合に発生する可能性があります。またstrict、タイプミスを見つけることができ、スコープ外になるとファイルハンドルが自動的にクリーンアップされることも意味します。

  • 意味のあるファイルハンドルを使用しています。この場合、画像に書き込むように見えます。

  • ファイルハンドルは。で終わります_fh。通常のスカラーのように使用しているのを見ると、おそらく間違いであることがわかります。

于 2008-11-29T12:29:11.757 に答える
11

ファイル全体をメモリに読み込むことができるほど小さい場合は、File::Slurpを使用します。非常に単純な API を使用して完全なファイルを読み書きするだけでなく、すべてのエラー チェックを行うため、ユーザーが行う必要はありません。

于 2008-11-25T21:42:29.097 に答える
6

ファイルを開いて読み取る最良の方法はありません。それは間違った質問です。ファイルの内容 どの時点でどのくらいのデータが必要ですか? 一度にすべてのデータが必要ですか? データで何をする必要がありますか? ファイルを開いて読み取る方法を考える前に、それらを理解する必要があります。

あなたが今していることはあなたに問題を引き起こしていますか?そうでない場合、解決すべきより良い問題はありませんか? :)

あなたの質問のほとんどは単なる構文であり、それはすべて Perl ドキュメント (特に ( perlopentut )で回答されています。質問で発生した問題のほとんどに回答するLearning Perlを選択することもできます。

幸運を、 :)

于 2008-11-25T22:06:59.157 に答える
5

Perl でファイルを開く最善の方法はたくさんあります。

$files_in_the_known_universe * $perl_programmers

...しかし、通常は誰がどのように行うのかを見るのは興味深いことです。私の好みの丸呑み (ファイル全体を一度に読む) の形式は次のとおりです。

use strict;
use warnings;

use IO::File;

my $file = shift @ARGV or die "what file?";

my $fh = IO::File->new( $file, '<' ) or die "$file: $!";
my $data = do { local $/; <$fh> };
$fh->close();

# If you didn't just run out of memory, you have:
printf "%d characters (possibly bytes)\n", length($data);

そして、行ごとに行くとき:

my $fh = IO::File->new( $file, '<' ) or die "$file: $!";
while ( my $line = <$fh> ) {
    print "Better than cat: $line";
}
$fh->close();

もちろん注意事項: これらは、私が毎日の作業のためにマッスル メモリにコミットしたアプローチにすぎず、解決しようとしている問題には根本的に不適切である可能性があります。

于 2008-11-26T04:14:20.383 に答える
5

OOの場合、私は好きです:

use FileHandle;
...
my $handle = FileHandle->new( "< $file_to_read" );
croak( "Could not open '$file_to_read'" ) unless $handle;
...
my $line1 = <$handle>;
my $line2 = $handle->getline;
my @lines = $handle->getlines;
$handle->close;
于 2008-11-26T01:47:16.280 に答える
5

かつて使っていた

open (FILEIN, "<", $inputfile) or die "...";
my @FileContents = <FILEIN>;
close FILEIN;

定型文を定期的に。最近ではFile::Slurp、メモリに完全に保持したい小さなファイル、Tie::Fileスケーラブルにアドレス指定したい大きなファイル、および/またはその場で変更したいファイルに使用します。

于 2008-11-26T12:27:05.207 に答える
3

ファイル全体 $file を変数 $text に 1 行で読み込みます

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

または関数として

$text = load_file($file);
sub load_file {local(@ARGV, $/) = @_; <>}
于 2008-11-30T00:32:23.017 に答える
2

これらのプログラムが生産性向上のためだけのものである場合は、何でも機能します! 必要と思われるだけのエラー処理を組み込みます。

ファイルが大きい場合、ファイル全体を読み取ることは、長期的には最善の方法ではない可能性があるため、行を配列にロードするのではなく、入力された行を処理することをお勧めします。

The Pragmatic Programmer (Hunt & Thomas) の章の 1 つから得た 1 つのヒントは、スライシングとダイシングを実行する前に、スクリプトでファイルのバックアップを保存することをお勧めします。

于 2008-11-25T21:01:29.913 に答える
2

演算子は||優先順位が高いため、結果を「open」に送信する前に最初に評価されます...言及したコードでは、代わりに「or」演算子を使用すると、その問題は発生しません。

open INPUT_FILE, "<$input_file"
  or die "Can't open $input_file: $!\n";
于 2008-12-01T10:32:46.407 に答える
1

ダミアン・コンウェイは次のようにします。

$data = readline!open(!((*{!$_},$/)=\$_)) for "filename";

しかし、私はあなたにそれをお勧めしません。

于 2008-12-01T04:02:24.930 に答える