改行コードの取り扱いについて勉強しなおした。
一つ前のエントリーを調べるに当たって勉強しなおしたのでまとめる。
\r, \n を各環境下で出力した場合、出力されるコード値それぞれ以下のようになる模様。
Linuxの場合
\r は \x0d として出力され、
\n は \x0a として出力される。
$ perl -e 'print "\r\n"' > sample.txt $ od -tx1c sample.txt 0000000 0d 0a \r \n 0000002
Windowsの場合
\r は \x0d として出力され、
\n は \x0d \x0a として出力される。
>perl -e "print qq(\r\n)" > sample.txt >debug sample.txt -d 351A:0100 0D 0D 0A 00 00 00 00 00-00 00 00 00 00 00 00 00 ...............
Perl内部では
\r は \x0d として出力され、
\n は \x0a として出力される。
Linuxで\r,\nを16進数出力
$ perl -e 'print unpack( "H*", "\r" ), "\n"'; 0d $ perl -e 'print unpack( "H*", "\n" ), "\n"'; 0a
Windowsで\r,\nを16進数出力
>perl -e "print unpack( 'H*', qq(\r) )"; 0d >perl -e "print unpack( 'H*', qq(\n) )"; 0a
Windowsにて、ファイル出力した場合のコード値とPerl内部のコード値が異なる
これに関しては、binmodeのドキュメントで詳しく説明がされていた。
Mac OS、全ての Unix 系、VMS の Stream_LF ファイルは テキストの外部表現として各行の末尾に 1 つの文字を 使っています(その文字は Mac OS では復帰で、 Unix とほとんどのVMS のファイルでは改行です)。 VMS, MS-DOS, MS-Windows 系といったその他のシステムでは、 プログラムからは \n は単純に \cJ に見えますが、 テキストファイルとして保存される場合は \cM\cJ の 2 文字になります。つまり、もしこれらのシステムで binmode() を使わないと、 ディスク上の \cM\cJ という並びは入力時に \n に変換され、 プログラムが出力した全ての \n は \cM\cJ に逆変換されます。 これはテキストファイルの場合は思い通りの結果でしょうが、 バイナリファイルの場合は悲惨です。
Perlの組み込み関数 binmode の翻訳 - perldoc.jp
なるほど。
改行コードの取り扱いが理解できた。
そして、binmodeが必要なタイミングというのもはっきりと分かった。