いろいろなプログラム言語があるがたいていどの言語もファイルを開いて読み書きする操作(関数やメソッド)が用意されている。
openと付く関数名が多いようだ。例えばPerlの場合は
open FILE, '<', 'filepath' or die $!;
とすれば'FILE'という変数にファイルオブジェクト(ファイルハンドル)というものを格納し以降はそれをつかって読み書きが出来る(上の例だと読み出しのみ)。
Pythonでは
f = open('filepath', 'r')
で変数fにファイルオブジェクトが入る。
Rubyでは
f = File.open('filepath', 'r')
PHPでも
$f = fopen('filepath', 'r');
とするだけであとは変数fに対して何かしらの処理をしていくことになる。
いらなくなったファイルにはそれぞれ
Perl:
close (FILE);
Python/Ruby:
f.close
PHP:
fclose($f);
として閉じる操作も用意されている。
Rubyではファイルを開く時に
File.open('filepath', 'r') { |f| fに対する処理・・・ }
とブロックコードを渡す事によって明示的にcloseを呼ばなくてもブロックの終わりで閉じてくれる。
その後は取得した変数fを使い内容を読み込んでいくのだが、1行だけ取得したいのかファイル全体を取得したいのか、または1文字だけでいいのか・・等、操作によって呼び出す関数も変わってくる。関数にgetsもしくはreadlineと付いたら多分1行、readと付いたらファイル全体、readlinesと付いたらファイル全体を1行ずつ配列に格納する。そんな覚え方をしている。getcは1文字だ。
read関数はRubyやPythonの場合引数を省略するとファイル全体、引数を与えると与えたサイズ分のバイトを読み込む。PHPのfread関数はサイズを省略できないので若干面倒だったりする。
$str = fread ($f, filesize("filepath"));
とこう書かないと駄目みたい(全体を読み込みたい場合)。
Perlについては上の書き方は今となっては推奨されなくなった書き方だ。
'FILE'という変数はグローバル変数になってしまう為、今は
open my $fh, '<', 'filepath' or die $!;
の方が推奨されている。
あるいはオブジェクト指向用のインターフェイスが用意されてて
use IO::File;
my $fh = IO::File->new('filepath');
と書く事も出来る。use IO::Fileした場合はそれぞれ
$fh->getc; $fh->getline; $fh->getlines;
とファイルオブジェクトのメソッドを呼び出す事が出来る。
それぞれ1文字、1行、ファイル全体を1行ずつ配列へ、といった感じだ。
他の言語と若干名前が違う。
ただしPerlには昔から使用されている山かっこ演算子を使う事でいちいち関数名を覚えなくてもファイルの内容を取得する事が出来る。
Perlの変数名にはシジル(sigil)と呼ばれる記号が付く。
このシジルによってどういったデータが欲しいのかをPerlが察してくれる訳だ。例えば
$line = <$fh>;
とした時は$lineの中身は1行分の文字列が格納されている。
@lines = <$fh>;
とした時は@linesは配列となり、ファイル全体の1行ずつが各要素となっている。
さらに
$lines = [<$fh>];
と、こう書いたら上の@linesのリファレンスが格納されている。
Perlには特殊変数の$/が用意されていて中には入力時のレコード区切り文字(デフォルト値は改行文字)が入っている。
これを無効にすると
my $lines = do { local $/; <$fh> };
で、ファイル全体が一つの文字列として格納される。
ちなみに配列に1行ずつ格納する時は改行文字も付いてきてしまう。
もし邪魔なら以下のようにすればいい。
@lines = map {chomp; $_} <$fh>;
これはmapに渡したブロックの中でデフォルト変数$_に対してchomp関数を呼び出し、chomp関数適用済みの$_をそれぞれ返してくる。
これを例えば
@lines = grep {chomp} <$fh>;
こう書けるんじゃないか、と思ってしまうがちょっとした落とし穴がある。
grep関数は渡したブロックや式の中で真となった要素を返すいわばフィルターのような役割をする。
ここではブロックの中でchomp関数を呼び出しているがこの関数は改行文字を取り除く処理をし、成功したかどうかのブール値を返す関数だ。
もし最後の行に改行が無かったらchomp関数は失敗したという事になり0を返す。その0が偽として扱われてしまう為、最後の行だけはどっかに消えてしまう。
という訳だ。
このコードを呼び出してみると分かりやすい
@lines = map {chomp} <$fh>;
mapはブロックの中の式の結果をそのまま返してくれるのでここではchomp関数が成功したかどうかの真偽値が入ってくる。具体的には1か0だ。
すべての行に改行文字が含まれていれば、例えば10行のファイルなら10個の1が入っているはずだ。もし最後の行に改行が無ければ配列の最後は0になっている。
要はchomp関数が失敗したという結果だ。
トラックバック(0)
トラックバックURL: http://blog.beanz-net.jp/beanz_mtos/mt-tb.cgi/24
コメントする