改行コード

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

概要

改行コード(広義)は以下の2種類であり、システム(ソフトウェア)により片方または両方が使用される。

  • キャリッジリターン: carriage returnCR、復帰)
  • ラインフィード(: line feedLF狭義の改行)またはニューライン(newline、line break または end-of-lineEOL

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

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

改行の数値表現

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

  • ASCII文字コードに基づくシステムでは、CR(復帰、0D(16進))、LF(改行、0A(16進))、またはCR+LFで表している。
  • Unicodeでは、CR (U+000D) とLF (U+000A) に加えて、「次の行」 (next line) を示すNEL (U+0085)、行区切り文字 (line separator) を示すLS (U+2028)、段落区切り文字 (paragraph separator) を示すPS (U+2029) が提供される。
  • EBCDICシステム
IBMメインフレームシステムでは主にNEL(Next Line、15(16進))を改行コードとして使う。EBCDICはCRとLFと呼ばれる制御文字も持つが、これらはASCIIにおけるCRとLFとは値が異なる。また、NELに対して異なる値を割り当てたEBCDICの亜種も存在する。なお固定長のデータセットでは、通常は改行コード自体が不要なため使用されない。
  • OpenVMSはレコードベースのファイルシステムを使用しており、テキストファイルの各行を1レコードとして保存する。保存する際は改行コードは記録されないが、アプリケーションから読み込まれる際に自動的に行終端記号を付加する機能がある。

インターネット上で用いられる、テキストによって情報をやりとりする通信プロトコルの多く(HTTPSMTPFTPIRCなど)はプロトコルレベルでCR+LFコードを用いるよう要求しているが、アプリケーションはLFコードにも対応することが推奨されている。これは初期のインターネットサーバの多くがDEC機によって構成されていた名残である。

歴史

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

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

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

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

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

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

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

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

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

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

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

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

関連項目

外部リンク