ファイルハンドルに対するbinmodeの変更が及ぼす影響を小さくしたい
ファイルハンドルをbinmode
で変更して,そのファイルハンドルを用いて何らかの処理を行いたい,という欲求がしばしばあると思います.
単純に書くと以下のようになるでしょう.
このコードではファイルハンドルを普通にopenして,それをawesome_function()
に渡して,そのawesome_function()
内でbinmode $fh, ':encoding(utf-8)'
を使ってファイルハンドルのencodingを変更して,そのファイルハンドルで何らかの処理を行っています.
ぱっと見これで良い感じがしますが,このコードには問題があって,awesome_function()
内でのファイルハンドル$fh
の変更は他の箇所,つまりawesome_function()
の外にも影響を及ぼします.
上のコードを例に取ると,awesome_function()
を呼ぶ前のファイルハンドル$fh
はencodingが変更されていませんが,呼び出した後のファイルハンドル$fh
はencodingが変更されています.これだと具合が悪い時がままある.
こうした場合に,ファイルハンドルへの変更をawesome_function()
内で留めたい場合どうすれば良いのかと考えた時に,とりあえずファイルハンドルを複製して,その複製したファイルハンドルに対して変更を与えてからそれを使って処理すれば良いのではないか,という感じになりました.こんな感じ.
awesome_function()
内でファイルハンドルを複製して *1,その複製したファイルハンドル$fh_copy
に対してbinmode
でencodingを変更してやってから$fh_copy
を使って処理を行なってやれば,元のファイルハンドルに変更を及ぼすことが無くなります.つまり,awesome_function()
を呼んだ後であっても元のファイルハンドルは変更されません.
こうした場合はファイルハンドルの複製でなんとかなるんじゃないかと思った次第です.なんか駄目そうだったら教えて下さい.
なおファイルハンドルの詳細な情報 (layer) はPerlIO
の関数であるget_layers()
に対してdetails
フラグを立てて実行すると参照することが出来ます.上記コードだと以下の様な出力が得られます.
$VAR1 = 'unix'; $VAR2 = undef; $VAR3 = 2098176; $VAR4 = 'perlio'; $VAR5 = undef; $VAR6 = 4195328; $VAR7 = 'encoding'; $VAR8 = 'utf-8-strict'; $VAR9 = 4228096;
この結果から,encodingがutf-8-strict
であることがわかりますね.
ちなみにdetails
を使ったPerlIO::get_layers
にのドキュメントには“Implementation details follow, please close your eyes.”とか書いてあって大変クール!
CLOSE YOUR EYES/YAMATO-男たちの大和 主題歌-
- アーティスト: 長渕剛
- 出版社/メーカー: フォーライフ ミュージックエンタテイメント
- 発売日: 2005/08/24
- メディア: CD
- クリック: 5回
- この商品を含むブログ (33件) を見る
*1:ファイルハンドルの複製についてはopen()
を参照して下さい http://perldoc.perl.org/functions/open.html