改行コード
出典: フリー百科事典『ウィキペディア(Wikipedia)』
改行コード(newline)とは、コンピュータにおいて、行の終端を表す文字または文字の連続である。
目次 |
[編集] 改行の数値表現
多くのシステムでは、改行コードを1つか2つの特殊文字の連続で表している。
- IBMのメインフレームシステムでは主にNEL(Next Line、0x15)を改行コードとして使う。EBCDICはCRとLFと呼ばれる制御文字も持つが、これらはASCIIにおけるCRとLFとは値が異なる。また、NELに対して異なる値を割り当てたEBCDICの亜種も存在する。
- OpenVMSはレコードベースのファイルシステムを使用しており、テキストファイルの各行を1レコードとして保存する。保存する際は改行コードは記録されないが、アプリケーションから読み込まれる際に自動的に行終端記号を付加する機能がある。
テキストによって情報をやりとりするインターネットプロトコルの多く(HTTP、SMTP、FTP、IRCなど)はプロトコルレベルでCR+LFコードを用いるよう要求しているが、アプリケーションはLFコードにも対応することが推奨されている。
[編集] 歴史
ASCIIコードは、ISOとASA(ANSIの前身)によって並行して開発されていた。1963年~1968年、ISOの草案はCR+LFとLFの両方を改行コードとしてサポートしていたが、ASAの草案ではCR+LFのみがサポートされていた。1964年から開発が開始されたMulticsオペレーティングシステムはLFを改行コードとして採用し、UNIXやUNIXに続くシステムもそれにならってLFを採用した。
CR+LFはASR-33のようなテレタイプ端末によく使われた。そのようなシステムでは、プリンタヘッドを新しい行の先頭に移動するという「改行」の動作を、現在行の先頭に移動するCR(キャリッジリターン)の動作と、新しい行に移動するLF(ラインフィード)という2つの動作に分割し、それぞれ独立して制御するよう設計されていた。そのため、例えば行の途中でLFを伴わない単独のCRを送り、そのまま通常文字を出力することで、先に出力した文字に重ね書きすることが可能であったし、CRを伴わない単独のLFを用いて新しい行の途中から文字を出力することも可能であった。
当時のシステムでは、テキストはプリンタとの互換性を考慮して構成される必要があった。アプリケーションからハードウェアの詳細を隠蔽するデバイスドライバという概念がまだ発展していなかったため、アプリケーションはテレタイプ端末と直接やりとりをし、テレタイプ端末の慣習に従う必要があったのだ。このシステムでは、プリンタヘッドが右端から復帰するのに1文字の時間では間に合わなかった。これがCRが先に送られた理由である。実際には、プリンタヘッドが停止するのを待つためにCR+LF+NUL(最後に「何もしない」という命令を送る)やCR+CR+LF(CRを二度送る)というシーケンスを送る必要があることもあった。このようなシステムが消滅してからはCR+LFのような2文字の改行コードは技術的な意味を持たないが、現在も一部のシステムで存続している。
QDOS(マイクロソフトが買収し、MS-DOSと改名した)がCR+LFを採用したのは、CP/Mの実装を真似たためだと考えられている。更に、CP/MがCR+LFを採用した理由はいくつかの説が考えられている。 一つは、CP/MはUNIXをモデルとしていたため、UNIXの著作権を侵害したとしてAT&T/ベル研究所から訴えられる可能性を軽減しようとしたという説だ。もう一つは、CP/MはRT-11のようなDECオペレーティングシステムをモデルとしており、DECはもともとテレタイプ端末としての使用を想定して設計されていたという説だ。
その原因が何であれ、この慣習は後のMicrosoft Windowsに継承されている。
[編集] プログラミングにおける改行コード
ポータブルなプログラムを記述するために、プログラミング言語は異なる改行コードを扱うためにある程度の抽象性を提供している。
C言語は'\n'
(改行)、'\r'
(復帰)の二つのエスケープシーケンスを提供している。しかし一般的な認識に反して、これらのエスケープシーケンスは一般的にはLFやCRと等価ではない。C言語は次の二つの事柄のみを保証している。
- これらのエスケープシーケンスはそれぞれ異なった環境依存の
char
型に収まる範囲の数字に変換される。 - テキストモードでファイルに書き込むとき、
'\n'
はシステムで使用されている改行コードに変換される。この改行コードは1文字に収まるとは限らない。逆にテキストモードで読み込む時、改行コードのシーケンスは'\n'
に変換される。バイナリモードにおいてはいかなる変換も行われない。
C言語の母体であるUNIXでは、改行シーケンスはLFであり、'\n'
は単純にその値として定義されている。内部表現と外部表現が一致しているので、変換は行われない。従ってテキストモードとバイナリモードは同じように振舞う。このためUNIXで開発をするプログラマはこれらの区別を無視することができ、結果として互換性を欠いたコードを書いてしまうことがある。
もう一つの問題として、CR+LFの使用を要求するインターネットプロトコルを使ってテキストをやりとりする場合がある。そのようなストリームに対し'\n'
を送るという方法はWindowsシステムにおいては正しく動作するが、UNIXにおいてはLFしか送信されないため、問題となる。これに対し、バイナリモードで'\r\n'
を送るという方法は多くのASCII互換システムにおいて正しく動作する。しかし、必ずしも一般的に成功するとは限らない。一つの解決策として、バイナリモードを使って目的の数値(\x0D\x0A)を直接送るとどのような場合も正しく動作する。
Javaも'\n'
、'\r'
といったエスケープシーケンスをサポートする。C言語と異なり、それぞれ0x0A、0x0Dを表すものであると保証されている。Javaの入出力ライブラリはこれらの文字を環境依存の改行コードに変換するということはしない。その代わり、末尾に改行コードを付加して行を出力する関数や、CR、LF、CR+LFのいずれをも改行コードとみなして行を読み込む関数を提供している(BufferedReader.readLine()
)。