PHPには、Linux、Mac、Windowsなどの異なるOS環境間で改行コードを内部的に自動で切り替えてくれるPHP_EOLという便利な定数が用意されている。Javaでの実装だとSystem.getProperty("line.separator")にあたると思う。PHP_EOLがPHPの内部ではどのように実装されているのか、いまさらながらPHP_EOLと改行コードについて書いてみた。
PHP_EOLが定義されているソースファイルをリーディングする
リーディングするソースコードのPHPバージョンはphp-5.3.1を使う。PHP_EOLの定義箇所は以下のヘッダファイルにあり、PHP_EOL以外の定義済み定数の大半もこのファイルで定義されている。
php-5.3.1/main/php.h の Line47 ~ 71あたり
#ifdef PHP_WIN32
#include "tsrm_win32.h"
・
・
#define PHP_EOL "\r\n"
// (OSがWindowsの場合に改行コードが\r\nになる)
#else
・
・
#if defined(__MacOSX__)
// ※__MacOSX__このマクロはMacOS10では使われてない
// らしい。なのでここの条件分岐にMacOS10は入らない
#define PHP_EOL "\r"
// (OSがMacOS9以前の場合に改行コードが\rになる)
#else
#define PHP_EOL "\n"
// (OSがMacOS10、Linux、Unixなどの場合に\nになる)
#endif
#endif
このように、OS環境によって、if文で条件分岐し改行コードの文字表現を\r\n、\r、\nとdefineしているシンプルなソースコードである。わかりやすいように一覧表にまとめてみると以下の関係になり、ネットでも検索すれば同じような一覧内容は確認できる。

各OS環境でPHP_EOLが出力する改行コードをASCIIコードで確認してみる
改行コードを標準出力しても分かりずらいので、PHPのord()関数をつかいASCIIコードに変換して出力してみたいと思う。(※Mac環境がないので、Linux、Windows環境のみで)
以下にASCIIコード一覧の抜粋があるが、そこにある太字のASCIIコードが返ってくることが予想できる。ここで問題なのがWindows環境であるCRLF(\r\n)である。そもそもCRLFというASCII文字は存在していない。いったいどのような値がかえるのか?

コマンドラインでスクリプトを実行した結果
下記、改行コードを生成するコマンドをOS環境を変えてコマンドラインから実行していってみる。またOS環境における差異を明確化させるために、strlen()関数で出力される改行コードの長さも測った。下記が結果内容である。php -r 'echo ord(PHP_EOL);' (改行コードをASCIIコードで出力)
Linux環境で実行した際の結果値:10
Windows環境で実行した際の結果値:13
php -r 'echo strlen(PHP_EOL);' (改行コードの長さを出力)
Linux環境で実行した際の結果値:1
Windows環境で実行した際の結果値:2
これらの結果から、疑問であったWindows環境における改行コードのASCIIコードの値は13と出力された。ASCIIコード一覧と照らしてみると、13 = CR = \rになる。このような値が返ってきたのはCRLF自身が、ASCIIコードのCR(\r)とLF(\n)を並べて表現しているからである。現にstrlen()関数で長さを取得するとWindows環境(CRLF)では2という値がかえり、2byteの文字列であることがわかる。そのためord()関数にPHP_EOL定数がPHP内部でOS環境を判定して、\r\nをセットしても、先頭1byteの\r = 13が返ってくるというわけである。これはord()関数の異常というわけでなく、正常動作であった。
Trackback URL
http://blog.fukaoi.org/2010/01/04/php_eol?tb=y&entry_id=19
XML