[Perlトップページ]

ファイル入出力

ファイルオープンとクローズ- open, close -

Perlに限らず、一般的にプログラムではファイルからデータを読み込み、 処理をした結果をファイルに出力します。 「繰り返し - while、for -」の ページでも簡単に紹介しましたが、ここではファイルからデータを 読み込むために必要なファイルオープンと、 ファイルをオープンし処理が終了した後に行う ファイルクローズについて説明します。

ファイルからデータを読み込むためには、まずファイルを開かなければいけません。そのためには、openという関数を使います。

open (ファイルハンドル, 'ファイル名');

繰り返し」のページでの例を再掲し、 詳しく説明します。

#!/usr/bin/perl

$inputfile="kadai5-3.txt";

open (FILE, $inputfile) or die "$!";
while (<FILE>) {
    print $_;
}
close (FILE);
(実行結果)

1995 100
1996 110
1997 120
1998 130
1999 140
2000 150
2001 160

ここから細かく見ていきます。open関数が使用されている行ですが、

open (FILE, $inputfile) or die "$!";

となっています。ここでの注意点は、

  1. $inputfile(つまりkadai5-3.txt)というファイルを開き、 FILEというファイルハンドルを指定する。
  2. ファイルオープンに失敗したら、or以下が実行される。
  3. $! にはオープンに失敗した際の メッセージが入れられて表示される。

まず、1のファイルハンドルですが、難しく考える必要はありません。 処理中にデータを読み込む際に毎回「kadai5-3.txt」と 指定するのは面倒くさいものです。それを簡略化してくれる、 kadai5-3.txt に対応する記号として FILE が設定されています。つまり、ファイルハンドルは、 今どのファイルを開いているか管理するための名前です。 データを読み込む際には、 kadai5-3.txt ではなく、 FILE を使います。ちなみに、 FILE は 別の文字列でもいいわけですが、慣習として大文字で記述するようです。 ですから、 F1 FIN など適当な表現が可能です。

次に2のファイルオープンの失敗についてです。これは、 「条件判断 - if -」で勉強した or の構文になっています。

open (FILE, $inputfile) or die "$!";
    A                          B

ここでの or は、Aが偽のときに、Bを実行する という意味です。ですので、ファイルオープンに失敗したときに、 or 以下のエラーメッセージの表示が実行されるようになっています。

ちなみに、ファイルオープンに失敗する理由としては、

ことがよくあります。ファイルオープンに失敗した場合には、まず上記の2点を確認してみてください。

最後に3の $! に入れられるメッセージについてです。 もしファイルオープンに失敗した場合、次のようなメッセージが表示されます。

No such file or directory at ./kadai7-1.pl line 3.
$!に入れられたメッセージ   dieが自動的に表示するメッセージ

このメッセージを手がかりにスクリプトを修正すればいいわけです。この dieopenの後に記述する方法は一般的ですので、 このまま覚えましょう。

上記のスクリプトでは、<FILE>1行読み込む という命令を表しています。読み込んだ結果、ファイルの終わりでは なかったらwhile文の中を実行します。読み込まれた1行分のデータは、 文字列として $_ というデフォルト変数に入れられます。それをprint文で表示させているわけです。

また、openの方法は、読み込み用や書き出し用など、目的に応じて使い分けないといけません。

記号 意味 用例
< 読み込み用(なくても可) open (FILE, '< file.txt'); open (FILE, 'file.txt');
> 書き込み用 (ファイルが存在したら上書き、存在しなければ新規作成) open (FILE, '> file.txt');
>> 追加書き込み用 open (FILE, '>> file.txt');
+< <に加えて読み書き両用 open (FILE, '+< file.txt');
+> >に加えて読み書き両用 open (FILE, '+< file.txt');
+>> >>に加えて読み書き両用 open (FILE, '+< file.txt');

そして、ファイルからのデータ入力やファイルへの出力が終わり、 ファイルハンドルを使用することがなくなったら close関数を使ってクローズします。

close (ファイルハンドル);

演習7-1

下記のスクリプトでは、存在しないファイル'kadai7-100.txt'を 読み込み専用で開こうとしている。スクリプトをkadai7-1.plとして作成し、 実行結果を確認せよ。

#!/usr/bin/perl

open (FILE, 'kadai7-100.txt') or die "$!";
close (FILE);

print, printfでの出力

ファイルに文字や数字を出力するには、printを使用します。

print ファイルハンドル (出力データ);

または

print ファイルハンドル 出力データ;

このファイルハンドルを省略すると標準出力(STDOUT) に出力されます。今までのprint関数の使い方は、 このファイルハンドルを省略していたわけです。

演習7-2

演習2-2の内容をkadai7-2.txt というファイルに出力したい。下記のスクリプトをkadai7-2.plとして 保存し、catを用いて実行結果を確認せよ。

#!/usr/bin/perl

$file = 'kadai7-2.txt';
open (OUT, ">$file") or die "$!";

$age = 18;
print OUT "私の年齢は $age 才です。\n";

print OUT "---ケース1---\n";
print OUT "365/7\n");

print OUT "---ケース2---\n";
print OUT 365/7, "\n";

print OUT "---ケース3---\n";
print OUT 365/7 . "\n");

print OUT "---ケース4---\n";
printf OUT "%f\n", 365/7;

print OUT "---ケース5---\n";
printf OUT "%5.2f\n", 365/7;

print OUT "---ケース6---\n";
printf OUT "%d\n", 365/7;
(実行結果の確認)
% cat kadai7-2.txt

私の年齢は 18 才です。
---ケース1---
365/7
---ケース2---
52.1428571428571---ケース3---
52.1428571428571
---ケース4---
52.142857
---ケース5---
52.14
---ケース6---
52

printf関数を使用すると、出力の書式を指定できます。演習7-2でも、

printf OUT "%5.2f\n", 365/7;

とありました。%f 「10進数の浮動小数点数を出力せよ」<という命令で、それに %5.2f と指定することで、 「小数点も含めて全体を5桁、うち小数部分を2桁で出力せよ」 となります。%fのような記号は書式変換記号 とよばれます。その他の書式変換記号は次の表を見てください。

書式変換記号 意味
%d 引数を10進数として出力
%f 引数を10進数浮動小数点数として出力
%c 引数を文字として出力
%s 引数を文字列として出力
%o 引数を符号なし8進数として出力
%x 引数を符号なし16進数として出力

これまでは、ファイルへの出力を見てきましたが、 標準出力(スクリーン)に %5.2f のような桁数を指定して出力 したい場合があります。このような場合、上述したように printfを使いますが、出力先にSTDOUT という標準出力を表すファイルハンドルを指定するか、 またはファイルハンドルを省略するか、どちらかの方法で実現します。

演習7-3

演習7-2ではファイルに出力していたが、今度は標準出力に出力したい。 下記のスクリプトをkadai7-3.plとして保存し、実行結果を確認せよ。

#!/usr/bin/perl

print STDOUT "---ケース4-1---\n";
printf STDOUT "%f\n", 365/7;

print "---ケース4-2---\n";
printf "%f\n", 365/7;

print STDOUT "---ケース5-2---\n";
printf STDOUT "%5.2f\n", 365/7;

print "---ケース5-2---\n";
printf "%5.2f\n", 365/7;

ファイルテスト演算子

open関数を使う際には、dieを併用して強制終了できることを学習しました。 Perlでは、ファイルテスト演算子を用いて、ファイルに 関する情報を得ることができます。たとえば、 ファイルやディレクトリが存在するかどうかを調べるには、 ファイルテスト演算子の -e が使われます。 また、その他のファイルテスト演算子についても学習しましょう。

演習7-4

下記のスクリプトでは、ファイルテスト演算子の -e を用いて、存在しないファイル 'kadai7-100.txt'の存在を確認している。スクリプトを kadai7-4.plとして作成し、実行結果を確認せよ。

#!/usr/bin/perl

$file = 'kadai7-100.txt';
if (-e $file) {
    print "ファイル$fileは存在します\n";
} else {
    print "ファイル$fileは存在しません\n";
}

演習7-5

下記のスクリプトでは、九九の結果をファイルkadai7-5.txtに書き出し、 ファイルテスト演算子の -s を用いて、 ファイルサイズを調べている。スクリプトをkadai7-5.plとして作成し、 実行結果を確認せよ。

#!/usr/bin/perl

$file = 'kadai7-5.txt';
open (FILE, ">$file") or die "$!";

foreach $count1 (1 .. 9) {
    foreach $count2 (1 .. 9) {
        printf FILE "%3d", $count1*$count2;
    }
    printf FILE "\n";
}
close (FILE);

$size = (-s $file);
print "ファイル $file のサイズは $size byteです。\n";
(実行結果)
ファイル kadai7-5.txt のサイズは 252 byteです。

(ファイル kadai7-5.txt の中身)
% cat kadai7-5.txt
  1  2  3  4  5  6  7  8  9
  2  4  6  8 10 12 14 16 18
  3  6  9 12 15 18 21 24 27
  4  8 12 16 20 24 28 32 36
  5 10 15 20 25 30 35 40 45
  6 12 18 24 30 36 42 48 54
  7 14 21 28 35 42 49 56 63
  8 16 24 32 40 48 56 64 72
  9 18 27 36 45 54 63 72 81

演習7-6

下記のスクリプトでは、 .pl の拡張子をもつファイルの 一覧を得て、 -M を用いて、現在から何日前に ファイルが作成されたか調べている。スクリプトを kadai7-6.plとして作成し、実行結果を確認せよ。

#!/usr/bin/perl

foreach (<*.pl>) {
    print $_, "\n";
    if (-M $_ >= 7 ) {
        print "このファイルは1週間以上前に作られました。\n";
    }
}
(実行結果例)

kadai3-1.pl
kadai3-2.pl
このファイルは1週間以上前に作られました。
kadai3-3.pl
このファイルは1週間以上前に作られました。
kadai3-4.pl
このファイルは1週間以上前に作られました。
kadai3-5.pl
このファイルは1週間以上前に作られました。
kadai6-1.pl
kadai6-6.pl
kadai7-1.pl
kadai7-2.pl
kadai7-3.pl
kadai7-4.pl
kadai7-5.pl
kadai7-6.pl

ファイルロック - flock -

これまでファイルへの出力を勉強してきましたが、 Webページ上の掲示板では、同時に同じファイルに書き込みがなされる 可能性があります。ですので、あるファイルに処理している間は 他の書き込みを排除しなくてはいけません。そこで、 flockという関数を使って、ファイルをロックします。 (正確には、flockはflockをブロックするのであり、openやflockをしない書き込みをブロックするわけではありません。)

flock (ファイルハンドル, 操作モード);
使い方 意味
flock (FILE, 1) 読み込み宣言ロック(ブロックモード)
flock (FILE, 2) 書き込み宣言ロック(ブロックモード)
flock (FILE, 5) 読み込み宣言ロック(非ブロックモード)
flock (FILE, 6) 書き込み宣言ロック(非ブロックモード)
flock (FILE, 8) ロック解除
モード 機能
ブロックモード 対象ファイルがロックされているとき、自分がロックできるまでプログラムを一時停止して待機する
非ブロックモード 対象ファイルがロックされているとき、自分がロックできるかどうかをすぐに真か偽で返す

[Perl講座] [須崎純一トップページ]
須崎純一 京都大学大学 工学研究科都市環境工学専攻 環境情報学講座