改行コード

改行コード とは、ワードプロセッサやコンピュータなどで、改行を表す制御文字である。日本では「改行コード」と総称する事が一般的なため、本項目では、キャリッジリターン  とラインフィード  の両方について記載する。

1. 概要
-----

改行コードは以下の2種類であり、システムにより片方または両方が使用される。

キャリッジリターン
ラインフィードまたはニューラインこれらの用語はタイプライターが由来である。タイプライターでは印字装置は固定され、紙の方が上下左右に移動することで、文字送りや行送りが行われる。英語などの左横書きにおける「キャリッジリターン」とは、紙を固定して移動する装置を元の位置に戻すことである。「ラインフィード」とは紙を必要な行だけ上に送ることである。

コンピュータでは、同じ文字コードを使用していても、改行コードは異なる場合があるため、異なるシステム間でのデータの際には、改行が正確に反映されない場合がある。

2. 改行の数値表現
----------

多くのシステムでは、改行コードを1つまたは連続する2つの特殊文字で表している。

ASCII文字コードに基づくシステムでは、CR、LF、またはCR+LFで表している。
LF:         UNIXやUnix系のシステム。Linux、ChromeOS、AIX、Xenix、macOS、BeOS、Amiga、RISC OSなど。
CR+LF:   CP/M、MP/M、MS-DOS、OS/2、Microsoft Windows。
CR:         コモドールによるシステム、Apple IIファミリ、Mac OS、OS-9。
Unicodeでは、CR  とLF  に加えて、「次の行」  を示すNEL 、行区切り文字  を示すLS 、段落区切り文字  を示すPS  が提供される。
EBCDICシステム IBMのメインフレームシステムでは主にNELを改行コードとして使う。EBCDICはCRとLFと呼ばれる制御文字も持つが、これらはASCIIにおけるCRとLFとは値が異なる。また、NELに対して異なる値を割り当てたEBCDICの亜種も存在する。なお固定長のデータセットでは、通常は改行コード自体が不要なため使用されない。
OpenVMSはレコードベースのファイルシステムを使用しており、テキストファイルの各行を１レコードとして保存する。保存する際は改行コードは記録されないが、アプリケーションから読み込まれる際に自動的に行終端記号を付加する機能がある。インターネット上で用いられる、テキストによって情報をやりとりする通信プロトコルの多くはプロトコルレベルでCR+LFコードを用いるよう要求しているが、アプリケーションはLFコードにも対応することが推奨されている。これは初期のインターネットサーバの多くがDEC機によって構成されていた名残である。

3. 歴史
-----

テレックスに用いられていたITA2では、「改行」の動作をCR ) + LF ) によって実現していた。すなわち、プリンタヘッドを新しい行の先頭に移動するという「改行」の動作を、現在行の先頭に移動するCRの動作と、新しい行に移動するLFという2つの動作に分割し、それぞれ独立して制御するよう設計されていた。そのため、例えば行の途中でLFを伴わない単独のCRを送り、そのまま通常文字を出力することで、先に出力した文字に重ね書きすることや、CRを伴わない単独のLFを用いて新しい行の途中から文字を出力することも可能だった。

ASCIIコードは、ISOとASAによって並行して開発されていた。1963年～1968年、ISOの草案はCR+LFとLFの両方を改行コードとしてサポートしていたが、ASAの草案ではCR+LFのみがサポートされていた。1964年から開発が開始されたMulticsオペレーティングシステムはLFを改行コードとして採用し、UNIXやUNIXに続くシステムもそれにならってLFを採用した。

当時のシステムでは、テキストはテレタイプ端末との互換性を考慮して構成される必要があった。アプリケーションからハードウェアの詳細を隠蔽するデバイスドライバという概念がまだ発展していなかったため、アプリケーションはテレタイプ端末と直接やりとりをし、テレタイプ端末の慣習に従う必要があったためである。このシステムでは、プリンタヘッドが右端から復帰するのに1文字の時間では間に合わなかった。これがCRが先に送られた理由である。実際には、プリンタヘッドが停止するのを待つためにCR+LF+NULやCR+CR+LFというシーケンスを送らなければいけないこともあった。このようなシステムが消滅してからはCR+LFのような2文字の改行コードは技術的な意味を持たないが、現在も一部のシステムで存続している。

86-DOSがCR+LFを採用したのは、CP/Mの実装を真似たためだと考えられている。更に、CP/MがCR+LFを採用した理由はいくつかの説が考えられている。1つは、CP/MはUNIXをモデルとしていたため、UNIXの著作権を侵害したとしてAT&T/ベル研究所から訴えられる可能性を軽減しようとしたという説、もう1つは、CP/MはRT-11のようなDECオペレーティングシステムをモデルとしており、DECはもともとテレタイプ端末としての使用を想定して設計されていたという説である。

この慣習は、後のWindowsに継承されている。

4. プログラミングにおける改行コード
-------------------

複数のオペレーティングシステムに対応できるプログラムを記述するために、プログラミング言語は異なる改行コードを扱うためにある程度の抽象性を提供している。

C言語では'\n'と '\r'の2つのエスケープシーケンスを提供している。言語処理系はこれらのエスケープシーケンスをそれぞれ異なった環境依存のchar型に収まる範囲のバイト列に変換する。例えばUNIXやWindows上の一般的な処理系ではそれぞれ、0A と 0D である。

ただし、I/O用のライブラリ中で'\n'に相当する数値が特殊な値として処理されるシステムもある。これらの出力関数ではテキストモードで開かれたファイルにデータを出力する時、'\n'の部分がシステムで使用されている改行コード列に変換された文字列がファイルに出力される。例えば、UNIXでは、改行コード列は「0A」であり、Windowsでは「0D 0A」、Macintoshでは「0D」である。また、入力関数fgetsやfread、readはテキストモードで開かれたファイルからデータを読み込む場合、ファイル中にシステム依存の改行コード列があれば、その部分を'\n'に対応する数値に変換したものを変数に格納する。ファイルがバイナリモードで開かれている場合には、どの入出力関数も数値を変換をせずそのままの値として読み書きする。

これらの関数は、「0D 0A」の使用を要求する通信プロトコルを使ってテキストをやりとりする場合に問題になる。そのようなストリームに対し、printf関数などを使い'\n'を出力すると、Windowsシステムでは期待通り「0D 0A」が送信されるが、UNIXでは「0A」しか送信されないため、問題となる。解決策として、バイナリモードを使って目的の数値を直接送るとどのような場合も正しく動作する。

Java言語でも'\n'、'\r'の2つのエスケープシーケンスを提供している。言語処理系はこれらのエスケープシーケンスを、それぞれ、16ビットの数値000A、000Dに変換する。

よく使われるjava.io.PrintStreamクラスのprintメソッドやprintlnメソッド、printfメソッドは、C言語の printf 関数とは異なり、これらの数値を特別扱いせず、環境依存の改行コードに変換しない。ただし、printfメソッドで使われる書式文字列中では「改行」を表現するための特殊な表記として「%n」を使える。printfメソッドはこの部分を実行環境依存の改行コードに置換した文字列を出力する。また、いずれのメソッドでも、出力されるバイト数、バイト順については設定された文字符号化方式に依存する。

5. 関連項目
-------

文字コード
ASCII
行 
キャリッジ・リターン

6. 外部リンク
--------

[1]- ウェイバックマシン