Walrus,Digit. | 一覧 | 検索 | 更新履歴(RSS) | 新規作成
はてなブックマークに追加 はてなブックマークを表示 編集 | 編集(管理者用) | 差分

Perlメモ/IO::Fileモジュール

編集

OOスタイルでファイルIOを行うためのIO::Fileモジュール。

オブジェクト指向(OO)スタイルならファイルハンドルをがりがりいじってないでIO::File、ということの他に、IO::Fileオブジェクトであればサブルーチンやメソッドなどとの受け渡しがスマートなども良いところです。

IO::Fileモジュール自体はIO::HandleIO::Seekableを継承していて、IO::Handleのread、write、getline、getlines、printなどの読み書きのためのメソッドや、IO::Seekableのseekなどのメソッドを使うことができます。

オープンとクローズ

編集

ファイルを開くにはopenメソッドを、閉じるにはcloseメソッドを使います。 IO::Fileオブジェクトをnewメソッドで生成してから、openメソッドでファイルを開きます。

use IO::File;

my $io = IO::File->new();
$io->open('test.txt', 'r') or die $!;
print <$io>;
$io->close;

以下のように、newメソッドにファイル名、モードなどを渡して、IO::Fileオブジェクト生成時に、ファイルオープンも行わせることもできます。

my $io = IO::File->new('test.txt', 'r') or die $!;

読み込み

IO::Fileオブジェクトは通常のファイルハンドルと同じように扱うことができます。したがって、"<FILEHANDLE>"の書式で、FILEHANDLEの部分にIO::Fileオブジェクトを指定して、読み込みを行うことができます。

また、こうする代わりに、IO::Fileオブジェクトのgetlineやgetlinesなどのメソッドを使うこともできます。

ファイルから一行読み込む

ファイルから一行読み込むには、getlineメソッドを使います。

use IO::File;

my $io = IO::File->new('test.txt', 'r') or die $!;
my @lines = $io->getline;
$io->close;
print @lines;

getlineメソッドはコンテキストによらず、一行だけ読み込むメソッドです。 "<FILEHANDLE>"とした場合はスカラ・コンテキストでは一行だけ、配列コンテキストでは全行を読み込みました。IO::Fileではコンテキストを変えるのではなく、getlineを使うかgetlinesを使うかで明確に切り替えます。

ファイルから全行読み込む

ファイルから全行読み込むには、getlinesメソッドを使います。

use IO::File;

my $io = IO::File->new('test.txt', 'r') or die $!;
my @lines = $io->getlines;
$io->close;
print @lines;

getlinesメソッドはコンテキストによらず、全行を読み込むメソッドです。 なお、全行というのは「残りの」全行です。例えば、以下のようにした場合は1行目がすでに読み込まれていますので、2行目からの残りの全行が読み込まれます。

use IO::File;

my $io = IO::File->new('test.txt', 'r') or die $!;
$io->getline;
my @lines = $io->getlines;
$io->close;
print @lines;

標準入出力から一行読み込む

標準入出力などをIO::Fileで開く時には、fdopenメソッドを使います。fdopenメソッドは引数にファイルデスクリプタ(file descripter)をとりますが、これはfilenoコマンドで取得できます。

標準入出力を開いてしまえば、あとはファイルを開いた時と同じようにgetlineやgetlinesで読み込み、それが済んだらcloseで閉じることができます。

use IO::File;

my $io = IO::File->new;
$io->fdopen(fileno(STDIN),"r");
my $line = $io->getline;
$io->close;
print $line;

ファイルへの書き込み

IO::Fileオブジェクトは通常のファイルハンドルと同じように扱うことができます。したがって、"print FILEHANDLE DATA"の書式で、FILEHANDLEの部分にIO::Fileオブジェクトを指定して、書き込みを行うことができます。また、flockでロックをするなどといったことも可能です。

こうする代わりに、IO::Fileオブジェクトのprintなどのメソッドを使うこともできます。

ファイルへの書き込み

IO::Fileオブジェクトを通常のファイルハンドルとみなして、print文で書き込むことができます。しかしその代わりに、IO::Fileオブジェクトのprintメソッドを使うこともできます。次のようにします。

use IO::File;

my $io = IO::File->new('test.txt', 'w');
$io->print("test\ntext\n");
$io->close;

printメソッドの他に、printflushというメソッドもあります。これは出力をバッファリングせず、即座にファイルに書き出します。例えば次のコードを実行し、標準入力待ちのタイミングで、'text.txt'のサイズを確認してみてください。また、printflushとしているところを、printに戻してから、同じように確認してみてください。

use IO::File;

my $io = IO::File->new('test.txt', 'w');
$io->printflush("test\ntext\n");
<STDIN>;
$io->close;

ファイルをロックして追記する

一般的なPerl環境(WindowsでもNTか2000、XP以降なら大丈夫)であれば、ファイルロックはflock。perldocでは次のように表示されますが、FILEHANDLEにはIO::Fileオブジェクトを指定しても大丈夫です。

flock FILEHANDLE,OPERATION
    Calls flock(2), or an emulation of it, on FILEHANDLE.

例えば、ファイルを追記モードで開き、ロック後に書き込みを行い、クローズします。

use IO::File;
use Fcntl qw(:flock);

my $io = IO::File->new('test.txt', 'a');
flock($io, LOCK_EX);
$io->print("test\n");
flock($io, LOCK_UN);
$io->close;

ファイルを読み書き両用で開く

モードとして以下のどちらかを指定します。

モード別記法備考
'+<''r+'読書き両方に使える。ファイルがないときはエラーになる。
'+>''w+'読書き両方に使える。オープン時点で空のデータで上書き(ファイルがないときは作成)される。

例えば、以下のようにしてファイルを作成、数行の書き込みを行った後、先頭行を読み込む、といったことができます。

use IO::File;
use Fcntl qw(:flock);

my $io = (-f 'test.txt') ? IO::File->new('test.txt', 'r+') : IO::File->new('test.txt', 'w+');
flock($io, LOCK_EX);
$io->print("test\nlines\nin\nit.");
$io->seek(0, 0);
print $io->getline;
flock($io, LOCK_UN);
$io->close;

モードはこちらの表が一覧できて便利。

コメント

[[#rcomment]]