Study of CGI

入出力処理

標準出力

何らかの入力をどこからか受け取る、そして何かをどこかに出力する、この2つをあわせて入出力処理といいます。

あまりにも概念が広すぎてわかりにくいですが、具体的には入力はキーボード、ファイル、ブラウザのフォームなどのからデータを見込み、出力はディスプレイ、ファイル、ブラウザなどにデータを送ります。

Perlは、標準入力(STDIN)、標準出力(STDOUT)、標準エラー(STDERR)の3つの標準ファイルハンドルを備えています。

ファイルハンドルについては後述しますが、入出力先を指定しない場合の出力先のことで、ターミナルやコマンドプロントでPerlを使った場合は、ターミナルやコマンドプロントへのキーボード入力や画面出力、CGIで使用した場合は標準入出力がネットワークになっています。つまり特定のブラウザ経由で起動されたCGIは、そのブラウザの情報を受け取りそのブラウザに対して出力を行います。

ファイルハンドル

ファイルオープン(作成)

ファイルハンドルとは、Perl プログラムが他のファイルを参照するときに使う名前のことで、独自の名前空間にて管理されているため、スカラー変数、配列、ハッシュなどと同じ名前が使うことが可能です。

ただし、スカラー変数、配列、ハッシュなどのように最初にが特別の文字を置くことはしないので、予約語との衝突を避けるためブロックラベルのように大文字で記述するようにします。

上記の標準装備以外のファイルハンドルを使う場合は、open 関数を併用して下記のように記述します。

open ( HANDLENAME , "filename" ) ;

これでfilenameというファイルが入力用に開かれ、HANDLENAMEというハンドルネームに関連づけられます。

そのファイルからデータを参照する場合は、ハンドルネームを使って操作することになります。

存在しないファイルを、書き込みが可能な形でファイルをオープンしようとした場合は、ファイルが新規で作成されます。

open ( HANDLENAME , ">filename" ) ;#書き込み専用

ファイルオープンの形式には以下のようなものがあります。

    読み取り 書き込み 追加 新規作成 上書き
< filename 読込み用 × × × ×
> filename 書込み用 (上書き) × ×
>> filename 書込み用 (追加) × ×
+< filename 両用 × × ×
+> filenames 両用(新規) ×
+>> filename 両用(追加) ×

ファイルクローズ

ファイルハンドルを使い終わったら close 関数によりファイルを閉じる必要があります。

Perl プログラムが終了したら時点で、ファイルハンドルは自動的にクローズされます。

通常ファイルへの入出力は即時に行われるのでは無く入出力用バッファに貯められ一定量になった段階かclose が行われた時に出力されます。

close ( HANDLE ) ;

読み込み

ファイルハンドルを使って開いたファイルを読み込む場合は、そのファイルを開いたファイルハンドルに対して操作を行います。

いったん開いたファイルハンドルはアングルブラケット(<と>)で囲んで使用します。

open ( HANDLE , "file.txt" ) ;
$data = <HANDLE> ;

この、アングルブラケットで囲まれたファイルハンドルは、呼び出されるたびに読み込んだ内容を一行ずつ出力します。そして、出力する内容が無くなったら(つまりファイルの最後まできたら)undefを返します。

ですから、全ての内容を読み込むには下記のように、whileを使う方法などがよく使われます。

open ( HANDLE , "file.txt" ) ;
while ( <HANDLE> ) {
$data = $_ ;
}

また、ファイルハンドルは次のように配列で受け取るとすべての内容を一度に読み込むことができます。

@array = <HANDLE> ;

書き込み

ファイルハンドルを使ってファイルに書き込みをする場合は、ファイルを書き込みが可能な形で開く必要があります。

open ( HANDLE , "> file.txt" ) ;#書込み用 (上書き)
open ( HANDLE , ">> file.txt" ) ; #書込み用 (追加)

これらの open 関数は成功すれば真をかえし、失敗(ファイルがない、パーミッションが間違っている等)すれば偽をかえします。

実際にファイルに書き込みをするのは読み込むときと同じでファイルハンドルに対して行います。

そして、ファイルハンドルが閉じられると、書き込みが完了します。

open ( HANDLE , "> file.txt" ) ;
print HANDLE $data ;
close ( HANDLE ) ;

ファイルの削除・ファイル名の変更

ファイルの削除を行う際にはunlink関数を、ファイル名の変更の際にはrename関数を使用します。

データ本体とシステムは名前を通してつながっています、つまりFデータを読み出すには名前が必要だということです。

unlink関数はその名前をひとつデータから削除します。通常、データが持つ名前はひとつだけですので、この時点で呼び出すことができなくなり使えなくなります、そして名前がすべて失われたとき、それを見ているものがいなければ、本人も消されてしまいます。

unlink ("fred");

print "what file do you want to delete?";

chomp ($name = <STDIN>);

unlink ($name);

また、unlinkには削除するファイルのリストを渡すこともできます。

unlink ("cowbird","starling");

unlinkの返り値は、削除に成功したファイルの数になります。

複数のファイルを指定した場合、削除に失敗したファイルがあっても、返り値は成功したファイルの数になりますので、失敗したファイルを知ることはできません。

ですから、どのファイルが削除に失敗したかを知るには、ファイルをひとつづつ削除する必要があります。(ひとつづつなら、成功すれば1失敗すれば0が返ります。)

foreach $file (<*.o>){
unlink ($file) || warm "haveing trouble deleting $file: $!";
}

ファイル変更関数のrenameでは、一番目の引数に現在のファイル名、二番目の引数に変更するファイル名を与えます。

そして、ファイル名の変更に成功すると真を、失敗すると偽を返します。

この返り値を利用して、ファイル名の変更が成功したか、失敗したかを判定することができます。

rename ( "fred" , "barnnuey") || die "Can't rename fred to barney: $!";

ディレクトリハンドル

ファイルの操作のために使われるのがファイルハンドルなら、それに対応するディレクトリ操作のための機能がディレクトリハンドルです。

ディレクトリハンドルは、ファイルハンドル同様に独自の名前空間で管理されています。また、最初にが特別の文字を置くことが無いなどの点もファイルハンドルと同様で、ファイルハンドルに対する注意事項と推奨事項がそのまま適用されます。

ただし、ディレクトリハンドルは読み込み専用で、特定のディレクトリ内のファイルのリストを読み込みます。

ディレクトリオープン・クローズ

ディレクトリハンドルを操作する場合は、opendir、closedir、readdirといった一連の関数を使用します。

ディレクトリのオープンにはopendir関数、クローズclosedir関数を使用します。

opendir(ETC,"/etc") || die "Cannot opendir /etc: $!";
・・・
closedir(ETC) ;

ディレクトリハンドルは、再オープンしようとしたときや、プログラムの終了時点で自動的にクローズされます。

ディレクトリの読み込み

opendir(ETC,"/etc") || die "Cannot opendir /etc: $!";
while ( $name = readdir(ETC)) {
  print "$name\n";
}
closedir(ETC) ;

ディレクトリの内容を読み込むときは、readdir関数を使います。

readdir関数はディレクトリハンドルを引数に持ち、そのディレクトリ内のファイル名をランダムにひとつ返します。

そしてすべてのファイル名を読み込むとreaddirはundefを返します。


ディレクトリの作成・削除

ディレクトリを作成する場合は、mkdir関数を、削除するときはrmdir関数を使用します。

mkdir関数はディレクトリ名と、パーミッションの元になるモード指定を受け取ります。

モードは数値にって指定され、パーミッションの内部表現にしたがって解釈されます。パーミッションについてよくわからない方は、モード0777と指定しておけば多くの場合うまくいきます。

mkdir("gravelpit",0777) || die "Cannot mkdir gravelpit: $!";

削除するときはrmdir関数を使用しますが、これは中身が空のディレクトリを削除します。

空でない場合は削除はできません。

rmdir("gravelpit") || die "Cannot rmdir gravelpit: $!";

ファイルテスト

ファイルを新たに作るとき、同名のファイルがすでに存在している場合、そのファイルの内容は上書きされ失われてしまいます。また、存在しないファイルを開こうとした場合は、エラーとなります。

Perl ではファイルやディレクトリ内のファイルの様々な属性をを調べるファイルテスト演算子が用意されています。

例えばファイルが存在するかどうかを調べるには、「-e」演算子を使います。これは、ファイルが存在すれば真を返し、ファイルが存在しなければ偽を返します。

$name = "index.html" ;
if ( -e $name) {
print "I see you already have a file named $name \n" ;
} else {
print "Perhaps you 'd like to make a file called $name \n" ;
}

ファイルテスト演算子

ファイルテスト演算子には他にも以下のようなものが用意されています。

これらの演算子はほとんどが単純に真か偽かを返します。

-r ファイルやディレクトリが読み出し可能
-w ファイルやディレクトリが書き込み可能
-x ファイルやディレクトリが実行可能
-o ファイルやディレクトリをこのユーザーが所有している
-R ファイルやディレクトリが、実行ユーザーではなく、実ユーザーによって読み出し可能
-W ファイルやディレクトリが、実行ユーザーではなく、実ユーザーによって書き込み可能
-X ファイルやディレクトリが、実行ユーザーではなく、実ユーザーによって実行可能
-O ファイルやディレクトリが、実行ユーザーではなく、実ユーザーによって所有されている
-e ファイルやディレクトリが存在している。
-z ファイルが存在していて、かつ大きさが「0」である
(ディレクトリの大きさは決して0にはならない)
-s ファイルやディレクトリが存在していて、かつ大きさが「0」でない
(バイト数で表したファイルの大きさが返値になる)
-f 普通のファイルである
-d ディレクトリである
-l シンボリックリンクである
-S ソケットである
-p 名前付きパイプである
-b ブロック特殊デバイスである
-c キャラクタ特殊デバイスである
-u ファイルやディレクトリが setuid されている
-g ファイルやディレクトリが setgid されている
-k ファイルやディレクトリの sticky ビットがセットされている
-t このファイルハンドルに対して isatty () が真である
-T テキストファイルである
-B バイナリファイルである
-M 内容が最後に変更されてからの日数を返す
-A 最後にアクセスされてからの日数を返す
-C inode が最後に変更されてからの日数を返す

またstat 関数と lstat 関数を使用するとファイルテスト演算子で得られない情報も取得することができます。

パーミッション

ファイルやディレクトリのパーミッションとは、そのファイルやディレクトリに誰が何をできるかを決めるものです。

perlではこのパーミッションをchmod関数を使い変更できます。

chmod関数は8進数のモードと、ファイル名のリストを受け取り、受け取ったファイルすべてのパーミッションを指定されたモードに変更しようとします。

chmod(06666,"fred","barney");

chmodは、パーミッションの変更が成功したファイルの個数を返します。unlink同様、失敗したファイルがあった場合、どのファイルが失敗したかを知ることはできません。

ですから、変更に失敗したファイルを知りたい場合は、unlink同様ひとつづつファイルを処理する必要があります。

foreach $file ("fred","barney"){
unless chmod(06666,$file){
warm "hmm... couldn't chmod $file.\$!";
}
}

ポイント

  1. ファイルを操作するときはファイルハンドル、ディレクトリ内容を読むときはディレクトリハンドルをつかう。
  2. ファイルオープンの形式には様々なものがあり、状況によって使い分ける。
  3. ファイル操作する場合は状況によりファイルテスト演算子を使う。
  4. ファイルの作成の場合とは違い、ファイル削除にはunlink、ディレクトリ作成はmkdir、ディレクトリではrmdirといった関数を使う必要があります。
Sub Study of CGI Regular

□新着

  • 2016/04/14
    ページ復旧
  • 2007/10/06
    Story Maker始動
  • 2007/06/13
    久々の更新
  • 2007/01/06
    logちょっとバージョンアップ
  • 2006/07/27
    ホームページのPerl 終了

□Topics

  • 2016/04/14
    サイト復旧
  • 2007/10/06
    StoryMaker始動
  • 2007/06/13
    今後にぜひご期待を!
  • 2006/06/26
    今後について
  • 2006/06/15
    環境の変化