Perl 再入門 : ファイルの存在チェック、読み込み、新規生成、追記

Perl でファイルの操作アレコレ。コレをマスターすれば、昔ながらの掲示板的な CGI が作れるようになる。

目次

ファイルの存在チェック

Perl でファイルの存在チェックをする方法。

my $logFileName = './test.log';

# -e はディレクトリでも真・-f はファイルなら真
if(-f $logFileName) {
  print('ファイルがあるよ');
}
else {
  print('ファイルがないよ');
}

if 文用に、-e-f といった存在チェックができる演算子がある。

条件を反転させるには、-f の手前にエクスクラメーションマーク ! を付ける。

if(! -f $logFileName) {
  print('ファイルないよ');
  exit 1;
}

ガード節のように使える。

ファイルの読み取り

ファイルの読み書きは open() 関数で行う。

# ファイルのパス
my $logFileName = './test.log';

# ファイルハンドル
my $logFile;

# ファイルを開く
eval {
  open($logFile, "<", $logFileName) or die($!);
};
if($@) {
  print("Error : $@");  # エラー時
  exit 1;
}

# 1行ずつ読み込み出力する
while(my $logLine = <$logFile>) {
  chomp($logLine);  # 行末の改行文字を削除する
  print($logLine . "<br>");  # HTML で改行するため
}

# ファイルを閉じる
close($logFile);

open() 関数の第2引数に書いた "<" 記号で、ファイルの読み書きのモードが変えられる。

オプション モード ファイルがない場合 ファイルがある場合
< 読取専用 エラー 変更なし
> 書込専用 新規生成 ファイルを空にする
>> 書込専用 新規生成 変更なし
+< 読書両用 エラー 変更なし
+> 読書両用 新規作成 ファイルを空にする
+>> 読書両用 新規作成 変更なし

モード指定がない場合は < と同じ、読取専用。

ファイルの新規生成

ということで、ファイルを新規作成したい場合は、>>> などの記号で書込モードにしてやれば良い。ファイルが既に存在する場合にどうしたいのかに合わせて選べば良い。

# 新たに生成したいファイルパス
my $newFileName = './new-file.log';

# ファイルハンドル
my $newFile;

# ファイルを生成する (既に存在する場合は追記モードとする)
eval {
  open($newFile, ">>", $newFileName) or die($!);
};
if($@) {
  print("Error : $@");
  exit 1;
}

書込モードにしている場合は、ファイルの内容の読取は上手くいかないので注意。

MacOS の /Library/WebServer/ 配下で動かしている場合、アクセス権がなくファイル生成に失敗してしまい、以下のエラーが出る。

Error : Permission denied at /Library/WebServer/CGI-Executables/test.cgi line 37.

このような場合は、ユーザホームディレクトリ配下など、ファイルを新規作成する権限がある場所で動かすようにしよう。

ファイルにテキストを書き込む・追記する

ファイルを > で開けば新規作成、>> で開けば追記モード、となるワケだが、実際に何かを追記してみる。

# 新たに生成したいファイルパス
my $newFileName = './new-file.log';

# ファイルハンドル
my $newFile;

# ファイルを生成する (既に存在する場合は追記モードとする)
eval {
  open($newFile, ">>", $newFileName) or die($!);
};
if($@) {
  exit 1;
}

# ファイルにテキストを書き込む
print($newFile, "テキストかきかき\n");

# ファイルを閉じる
close($newFile);

# 追記したファイルを読取専用で開き直す
eval {
  open($newFile, "<", $newFileName) or die($!);
};
if($@) {
  exit 1;
}

# ファイルを1行ずつ読み込む
while(my $line = <$newFile>) {
  print($line);
}

# 閉じる
close($newFile);

こんな感じ。print() の第1引数にファイルハンドルを渡し、第2引数で書き込むテキストを与えてやる。

今日はココまで

コレでファイルの読み書きのやり方は分かった。

よくある掲示板の CGI なんかだと、投稿内容はログファイルにタブ区切りで TSV 風に保存してあるのが多いかな。表示順を考慮して1行目に追記するようにするとか、スレッド管理のために区切り方を変えるとか、機能に応じて作り方を変えてる感じ。

ファイルの新規生成もできるので、「すえぽんさいと」にあった「Web Editor」のような、サーバ上で動作するエディタみたいなモノも作れるだろう。