2011-03-22
■[Perl] 続・はじめてのPerl 8章
今日も(ry
8.1 古い方法
ファイルハンドルはデータ型の1つ
ライブラリや、コードの他の部分で共有するには?
型グロブや型グロブリファレンスを使う
型グロブ
名前のすべてのパッケージ変数を指すポインタを格納している
型グロブを別の型グロブに代入することで、同じデータの別名を作ることができる
名前をファイルハンドルとして扱うとき、Perlは型グロブのファイルハンドル部を探す
型グロブはシンボルテーブルを操作する
つまり、パッケージ変数を処理する
open LOG_FH, ">> log.txt" or die $!; log_message( *LOG_FH, 'log message' ); close LOG_FH; sub log_message { local *FH = shift; print FH @_, "\n"; }
上記のコードで、localを使う理由
パッケージ変数はレキシカル変数になれないので、FHをmyで宣言することはできない
localを付けないFHに代入した場合
スクリプト内のどこかで、FHという名前が付けられているものを壊してしまう
localを付けるたFHに代入した場合
log_messageサブルーチンの実行中、FHという名前には一時的な値が格納される
サブルーチンから制御が戻るときに、PerlはFHを元の値に戻す
これらのやり方は「古い方法」
8.2 改良された方法
openで、ファイルハンドルリファレンスを作れるように
Perl5.6以降から
ファイルハンドルに指定できるのは、値がundefのスカラー変数
スカラー変数がundefでなかった場合
strictプラグマを使用しているとエラーとなり動作しない
ファイルハンドルに指定する変数は、openの中で宣言可能
飾りなしのファイルハンドルを使っていた箇所で、
スカラー変数のファイルハンドルリファレンスを使える
スカラー変数のファイルハンドルリファレンスは、
スコープから外れる、または、他の値が代入されるとファイルをクローズする
明示的にクローズする必要はない
# openの中で変数の宣言 open my $log_fh, ">> log.txt" or die $!; log_message( $log_fh, "log message"); sub log_message { my $fh = shift; # 出力 print $fh @_, "\n"; }
8.3 さらによい方法
3引数形式のopenを使う
2引数形式では、第2引数で指定した文字列をPerlが正しく解釈しない可能性がある
# 3引数形式のopen open my $log_fh, '>>', 'log.txt' or die $!;
8.4 IO::Handle
IO::Handle
入出力全般の基底クラス
ファイルだけではなく、多くのものを処理する
Perlは、裏でIO::Handleモジュールを使用している
ファイルハンドルスカラーは、実際はオブジェクト
新しいIOモジュールを作ること以外で、IO::Handleは直接使わないようにするべき
IO::Handleの派生モジュールを使用するべき
Perl組み込みのopenですでにできることも含まれている
できることは、Perlのバージョンで異なる
組み込み関数でできることを、モジュールインターフェイスで利用する理由
どのモジュールを使い入出力を行うのか先延ばしできる
モジュール名を変更するだけで、動作の切り替えができる
8.4.1 IO::File
IO::File
IO::Handleの派生クラス
ファイルを操作する
Perlのコアモジュール
use IO::File; # 1引数形式のコンストラクタ my $fh = IO::File->new( '> log.txt' ) || die $!; # 2引数形式のコンストラクタ # 第2引数はファイルハンドルのアクセスモード # ANSI Cのfopenのモード文字列 # モード文字列は組み込みのopenでも使える my $read_fh = IO::File->new( 'log.txt', 'r' ); my $write_fh= IO::File->new( 'log.txt', 'w' ); # アクセスモード引数にビットマスクを使うことで、より細かく動作をコントロール可能 # 定数は、IO::Fileモジュールが提供 my $append_fh = IO::File->new( 'log.txt', O_WRONLY|O_APPEND ); # 一時ファイルの作成 # 読み書き用のファイルハンドルを取得できる my $temp_fh = IO::File->new_tmpfile; # 明示的にクローズ $temp_fh->close; undef $append_fh; # 明示的にクローズしない場合、 # ファイルハンドルは、スコープから外れるとクローズされる
8.4.2 無名IO::Fileオブジェクト
IO::Fileオブジェクトは、スカラー変数以外にも代入可能
配列の要素
ハッシュの値
8.4.3 IO::Scalar
IO::Scalar
スカラーに情報を追加できるファイルハンドルリファレンスを作成する
Perlのコアモジュールではない
use IO::Scalar; my $string_log = ''; my $scalar_fh = IO::Scalar->new( \$string_log ); # メッセージは、$string_logに格納される print $scalar_fh "Hello, IO::Scalar!\n"; print $scalar_fh "Hello, IO::Scalar!!\n"; print $scalar_fh "Hello, IO::Scalar!!!\n"; $scalar_fh = IO::Scalar->new( \$string_log ); while ( <$scalar_fh> ) { print; }
# Perl5.8以降では、IO::Scalarを使わずに同じことが可能 my $string_log = (); open( my $fh, '>>', \$string_log ) || die $!; print $fh "not use IO::Scalar!\n"; print $fh "not use IO::Scalar!!\n"; print $fh "not use IO::Scalar!!!\n"; print $fh "not use IO::Scalar!!!!\n"; open( $fh, '<', \$string_log ) || die $!; while ( <$fh> ) { print; }
8.4.4 IO::Tee
IO::Tee
出力を多重化できる
第1引数が入力ファイルハンドルの場合
Teeファイルハンドルを使い、入力ファイルからの読み出しと出力ファイルへの書き込みの両方が可能
第1引数以外は、出力ファイルハンドルである必要がある
use IO::File; use IO::Scalar; use IO::Tee; # 出力の多重化 { my $log_fh1 = IO::File->new( 'log1.txt', 'w' ); my $log_fh2 = IO::File->new( 'log2.txt', 'w' ); my $tee_fh = IO::Tee->new( $log_fh1, $log_fh2 ); print $tee_fh "output tee_fh!\n"; } # 第一引数が入力ファイルハンドル { my $read_fh = IO::File->new( 'log.txt', 'r' ); my $log_fh1 = IO::File->new( 'log1.txt', 'w' ); my $log_fh2 = IO::File->new( 'log2.txt', 'w' ); my $tee_fh = IO::Tee->new( $read_fh, $log_fh1, $log_fh2 ); while ( <$tee_fh> ) {}; print $tee_fh "end\n"; }
8.5 ディレクトリハンドルリファレンス
# ファイルハンドルリファレンスと同様に、 # ディレクトリハンドルリファレンスの作成も可能 opendir my $dh, '.' or die $!; for my $file ( readdir( $dh ) ){ print $file, "\n"; }
8.5.1 IO::Dir
IO::Dir
Perlコアモジュール
Perl5.6以降から
Perlの組み込み機能をオブジェクト指向インターフェイスで提供
use IO::Dir; my $dir_fh = IO::Dir->new( '.' ) || die $!; while( defined( my $file = $dir_fh->read ) ) { print "$file\n"; }
感想
IO::Teeの第一引数が入力ファイルハンドルのものが、動作が想像してたものと違った。
本のニュアンスでは、明示的に書き込まないと書き込まれないように受け取れたが、
実際サンプルコードを動かすと、読み込むと同時に書き込みが行われているようだ。
あとでちゃんと調べよう。
- 作者: Randal L. Schwartz,brian d foy,Tom Phoenix,吉川英興,伊藤直也,田中慎司,株式会社ロングテール/長尾高弘
- 出版社/メーカー: オライリー・ジャパン
- 発売日: 2006/10/21
- メディア: 大型本
- 購入: 9人 クリック: 389回
- この商品を含むブログ (99件) を見る
トラックバック - http://d.hatena.ne.jp/tyamaguc07/20110322/p1
リンク元
- 1 http://d.hatena.ne.jp/gallu/20110321/p1
- 1 http://d.hatena.ne.jp/gallu/20110321/p2
- 1 http://d.hatena.ne.jp/keyword/Perl
- 1 http://search.hatena.ne.jp/search?word=モダンperl&site=d.hatena.ne.jp&from=
- 1 http://www.google.co.jp/search?hl=ja&biw=1179&bih=748&q=File->new_tmpfile+書き込み&aq=f&aqi=&aql=&oq=
- 1 http://www.google.co.jp/search?hl=ja&client=firefox-a&hs=4AG&rlz=1R1GGGL_en___JP359&q=perl+画像+位置情報&aq=f&aqi=&aql=&oq=
- 1 http://www.google.co.jp/search?hl=ja&client=firefox-a&hs=Mta&rlz=1R1GGGL_en___JP359&q=perl+画像+位置情報&aq=f&aqi=&aql=&oq=
- 1 http://www.google.co.jp/search?hl=ja&client=safari&rls=en&prmdo=1&tbs=blg:1&q=perl++title+取得&aq=f&aqi=&aql=&oq=
- 1 http://www.google.co.jp/search?hl=ja&q=サブルーチン+静的変数&aq=f&aqi=&aql=&oq=
- 1 http://www.google.co.jp/search?hl=ja&q=ssleay+インストール 失敗&lr=lang_ja&rlz=1I7GUEA_ja
