ここ最近の私がやらかした極めてみっともない失敗を晒す(1) open()の成否をif()で確認しようとした

 前々から「ブログでプログラムの話題に触れたらいつかはやっておかないといけないだろうなあと思っていた事をやってみようかと思い立って、ちょうどネタもあったし唐突にコーナーを始めてみることにしました。
 世の中に手本となる記事は数あれど、これから僕が書こうとしている記事は恐らくほとんどの人間にしてみれば全く役に立たないどころか害になる可能性を否定しきれないことを予めご報告しておきます。みんなは真似するなよ(未来の自分も含む)!

 今回は「open()の成否をif(<ファイルハンドル>)で確認しようとした」です。通常はその場でopenに成功したか確認するのが普通ですが、このときはちょっとした実験のつもりで下記のようなことをやってみました。

#!/usr/bin/perl

use strict;

open FILE, "./test.txt";

#### 間にいくつかの処理を挟む ####

if (<FILE>) {
    while (<FILE>) {
	chomp;
	print "$_\n";
    }
}

close FILE;'

exit 0;


上記のようなコードの場合、if ()の箇所で1行ファイルの中身が読まれてしまうため、実行結果に表示されるファイルの中身は2行めからになります。阿呆ですねこのコード書いた人!

正解は以下の通りです。

#!/usr/bin/perl

use strict;
use IO::File;

my $handle = new IO::File "./test.txt", "r";

#### 間にいくつかの処理を挟む ####

if (!defined $handle) {
    goto abort_func;
}

while (<$handle>) {
    chomp;
    print "$_\n";
}

undef $handle;

exit 0;


abort_func:

print "Error occured.\n";
exit 1;


手動でフラグを立てて力業で管理するよりは素直にモジュールに頼っちゃった方がごたつかなくてよいです。
というかそもそも「ファイルを開くのは書き込み|読み込みたい直前にする」という鉄則を守るべきでしょう。

こんなしょうもないミスかますとかほんとしょうもない。

結論: ファイルが開けたか後でチェックしたい場合はIO::Fileを使う

根本的な結論: そもそもファイルを開くタイミングは書き込み|読み込みたい直前にする