Perlでは、ファイルを操作するためにopenを使ってディスクリプタを開きます。標準ディスクリプタ(STDIN、STDOUT、STDERR)に加えて、自分で作成したものを管理することもできます。
Perlは、異なるタイプのファイルやエンコーディングを正しく処理するために、入出力レイヤー(:encoding、:utf8、:rawなど)という概念を利用しています。デフォルトでは、Perlはテキストモード(行の改行を含む)またはバイナリモードで動作します。
open my $fh, '<:encoding(UTF-8)', 'file.txt' or die $!; while (my $line = <$fh>) { print $line; } close $fh;
open my $fh, '<:raw', 'image.bin' or die $!; read($fh, my $data, -s 'image.bin'); close $fh;
レイヤーの正しい選択(バイナリには:raw、テキストには:encoding(NAME))は、正しい読み書きを保証します。
open FH, '<', $fileを使ってファイルを開き、バイナリデータを読み取った場合、常に正しい結果が得られますか?
回答: いいえ!:rawを指定しない場合、Perlは特定のプラットフォームで改行文字を自動的に変換します(例えば、WindowsではCRLFがLFに変わります)。バイナリファイルを読む際は常に:rawモードを使用してください:
open my $fh, '<:raw', 'file.bin';
物語
ある企業のプロジェクトで、開発者はエンコーディングを指定せずにテキストログを扱っていました。その結果、UTF-8のログが時々「壊れ」、キリル文字を含むバイトを誤って解釈したため、ファイルが壊れて読み取られました。このエラーは、
openの呼び出しで:encoding(UTF-8)レイヤーを明示的に追加した後に解決されました。
物語
Windowsでバイナリファイルをコピーする際に、
open FH, '<', 'binfile.dat'を使ってデータを読み取り、モードを指定せずに書き込んでいました。その結果、改行変換のために画像が「壊れ」、無効なバイナリデータが生成されました。:rawレイヤーが問題を修正しました。
物語
外部APIでは、STDOUTの出力がUTF-8であることが要求されていましたが、プログラマーはレイヤーを変更せずに
:encoding(UTF-8)の適用が明示的に行われた後、問題は解消されました。