PerlならサンプルコードPerl入門

2008-07-24

読み込み時のエラーを考慮したファイルリードの記述方法

  1. Perl
  2. ファイル入出力

 信頼性のないハンドルから読み込みを行うには、読み込み時のエラー処理を正しく行う必要があります。信頼性のないハンドルの例はソケットです。ソケットから読み込む際は、きっちりとエラー処理をします。

 ここでは、簡便のためにファイルハンドルを使います。

use strict;
use warnings;

# 読み込み時のエラーを考慮したファイルリードの書き方
# 読み込みたいファイル名
my $file = shift;

print "1: 読み込み時のエラーを考慮したファイルリードの書き方。\n";
open(my $fh, "<", $file)
  or die "Cannot open $file: $!";

for (;;) {
  # $! を未定義にしておく
  undef $!;
  my $line;
  
  unless (defined($line = readline $fh)){
    # readlineの戻り値がundefになるのは、EOFかエラーの場合。
    
    if ($!) {
      # $!がセットされるのは読み込みエラーの場合
      die "$!";
    }
    else {
      # $! がセットされないのは、EOFの場合
      # ファイルの終わりに達したのでforループから脱出
      last; 
    }
  }
    
  # 処理 ...
  print $line;
}
close $fh;

コード解説

open(my $fh, "<", $file)
  or die "Cannot open $file: $!";

# (1)無限ループの作り方
for (;;) {
    undef $!;
    my $line;
  
    # (2)ファイルリードエラーを知る方法
    unless (defined($line = readline $fh)) {
      if ($!) {
        die "$!";
      }
      else {
        last;
      }
    }
    # 処理 ...
}
(1)無限ループの作り方
for (;;) {

}
# あるいは
while (1) {

}

 for文の条件部に何も記述しないで;;とすれば、無限ループになります。while文の条件部に1を与えても無限ループを作成できます。

(2)ファイルリードエラーを知る方法
  undef $!;
  unless (defined($line = readline $fh)) {
    if ($!) {
      die "$!";
    }
    else {
      last;
    }
  }

 ファイルリードのエラーの存在を知るには、まずreadline関数の戻り値がundefかどうかを確かめます。undefの場合は、エラーが発生しているかファイルの終わりに到達したかどちらかです。

 さらに、$!を調べます。エラーが発生した場合は、$!に値がセットされます。ファイルの終わりに到達した場合は、$!は未定義のままです。$!が存在する場合はエラー処理を、存在しない場合はEOFに到達したので、last でforループを抜けます。