2009年04月09日 00:15 [Edit]
バイナリとテキストの本当の違い
うーむ、Wikipediaですら「見た目」の違いしか説明していない。
バイナリ - Wikipediaコンピュータが扱うすべてのデータはバイナリデータ(バイトの並び)であり、プレーンテキスト(または単にテキスト)もバイナリデータの一種ではあるが、通常バイナリとテキストは対比して用いられる。テキストとはデータの内容すべてを人間が読んで理解できる (human-readable) 表現形式を指し、バイナリとはそうでない表現形式を指すことが多い。Binary file - Wikipedia, the free encyclopedia
A binary file (.bin) is a computer file which may contain any type of data, encoded in binary form for computer storage and processing purposes; for example, computer document files containing formatted text. Many binary file formats contain parts that can be interpreted as text; binary files that contain only textual data - without, for example, any formatting information - are called plain text files.
バイナリーとテキストの本当の違い、それは「終わり」にある。
- 「終わり」がはじめにわかるのが、バイナリー。
- 「終わり」が来るまで「終わらない」のが、テキスト。
本質的な違いは、これだけである。
もう少し具体的に言うと、Pascal String はバイナリー、C String はテキストである。Pascalをご存知ない方のために補足すると、 Pascal では最初の 1 byte が文字列の長さを表していた。それに対し、CのString はよく知られているように\0が来るまで終わらない。
上の定義を、もう少し専門的に言い直すと、こうなる。
- 仕様、メタデータ、またはヘッダーで「終わり」を先に決めておくのがバイナリー
- 「データはここで終わり」という信号が来るまで「終わりがない」のがテキスト
バイナリーとテキストの特長と欠点は、すべてこの定義から導出できる。
バイナリーの特長は、「待つ」ことなしにデータの処理を始められることと、あらゆる「バイト」を公平に扱えること。この特長により、同じデータであればバイナリーの方がより高速に処理でき、プログラムも簡単に書けることが多い。
その代わり、データをそこから「拡張」することがすごく難しい。なにしろ「終わり」が「あらかじめ」決まっているのだ。バイナリーを「拡張」する方法は二つ。「あらかじめ隙間をあけておく」か、「以下続く」コードをあらかじめ定めておくか。後者の方法は一種の「テキスト化」とも見なせる。拡張性はないのがデフォルトで、あっても「あらかじめ開けておいた隙間を使う」に留まっている。
テキストはまさに逆。「データの終わり」が来ないとデータ処理が開始できないし、「データの終わり」というデータそのものは特別扱いしなければならない。「データの終わり」として定めた信号を「単なるデータ」として扱う場合には、「エスケープ」しなければならない。
その代わり、データはいくらでも拡張できるし、データを入れ子(nest)にするのも簡単だ。例えばJSONでは"が「文字列の終わり」(始まりでもあるが)、]が「配列の終わり」、}が「オブジェクト(ハッシュ)の終わり」だ。これらの「終わり」を「文字」として扱いたい場合には、エスケープする。
このことは、さらに重要かつ決定的な違いをもたらす。バイナリーを扱うためには、仕様が先になければならないが、テキストでは仕様は後でもかまわないのだ。HTMLがなぜこれほどの成功をおさめたかといえば、仕様が現実の後を追いかけてきたというのが最大の理由だろう。
ところで、テキストはバイナリーの連なりとしても表現でき、そして実際にそうなっている。「バイト列」というテキストは、「バイト」というバイナリーの連なりで表現されている。
ここで「バイト」(byte)を正確に定義しておこう。ここでもまたWikipediaにはちょっと裏切られた。英語版の方は少しましであるが。
バイト (情報) - Wikipedia通常、1バイトは2進数の8桁、即ち8ビット(bit)である。この場合、連続した256(28)個の整数(符号無しで0から255、符号付きで-128から+127、など)を表すことができる。Byte - Wikipedia, the free encyclopedia
A byte (pronounced IPA: /ba?t/) is a basic unit of measurement of information storage in computer science.
バイトの正確な定義、それは「コンピューターが一度に扱える最小の情報」である。それより小さな情報は「まとめて」扱わなければならない。「理論上最小の情報量である」1ビット(bit)が1バイトであるコンピューターも当然ありえ、実際元祖 turing machine はそうなっている。もっとも現代のコンピューターでは、1バイトはほとんど8ビットである。現代のコンピューターは、bit by bit ではなく byte by byte でしか情報を処理できない。1ビットいじる場合でも、1バイトづつ処理しなければならない。
そう。「1バイトは8ビット」という取り決めそのものが、バイトをバイナリーたらしめているのだ。
このことは、「文字」、すなわち char にも敷衍できる。まだアルファベットしかなかった頃には 1バイト = 1文字でよかったが、世界中の文字を char に収まるようにしようとするとそれでは足りない。「16bitで足りるんじゃね」と想像力の足りない人々が、Unicode 1.0を制定してしまった。
文字列はテキストでも、文字そのものはバイナリー。
だからこそ、文字というバイナリーを設計するときにはずっと慎重にならなければならなかったのだ。その余裕がなくとも、せめて「もっと隙間を開けておいて」おくべきだったのだ。
「どれだけ隙間を開けておくか」をあらかじめ予想するのは実に難しい。インターネットの開始時、32bitは「無限」に近いほど広く感じられただろう。だからこそ「今日までもった」のであるが、今ではその有限性が「今、そこにある危機」となっている。かといって、当時のコンピューターの性能でいきなり128bitはあまりに非現実的であっただろう。そして「バイト」と同じく、「パケット」はバイナリーで、これを「テキスト化」するのはかなり難しい。難しいので「テキスト化」はIPではなくTCPという「一つ上の階層」でやっている。
いずれにせよ、「バイト」や「パケット」は、今までもバイナリーだったし、これからもバイナリーであり続けるだろう。「テキストのアトム」としてのバイナリーさえきちんと抑えておけば、あとは「テキスト」でしのげる。これが Unix で得た最大の教訓の一つではないか。
404 Blog Not Found:デバッグより重要なもの迷ったら、テキストにしておけ。
バイナリーがいいと確信してても、テキストにしておけ。
どうしてもバイナリーが欲しかったら、テキスト化する方法も一緒に作っておけ。
これこそが、最も大事な富豪プログラミングだという確信は、年々強くばかりだ。
Dan the Textual Blogger
この記事へのトラックバックURL
>年々強く(なる)ばかりだ。
ですよね?
ファイルシステム上のテキストファイルはバイナリファイルか?
紙テープに出力したテキストデータはどうなるんだ?
終わりになんか違いがあるわけがない。
もちろん、仰っていることは正しい部分もありますが、そうではない部分もあります。
バイナリにも終わりがないものもあります。
たとえば、RGBデータにXYのピクセル数とRowBytesの情報を記述したヘッダーをつけて保存したファイルは終わりがありません。
前のコメントもそうですね。
テキストもバイナリも本質的な違いはありません。
それは正しいですが、テキストとバイナリの違いは、
そのデータをいわゆる文字コード表と照らし合わせて、「翻訳」したものが、意味のある(人間がわかる)データであった場合には、テキストデータ、意味のないものの場合には、バイナリデータ、それだけのことです。
もちろん、データを扱うプログラム(ソフト)によって違います。
例えば、同じデータでも
printf("%s")とやった場合は、テキストになりますが、同じデータをprintf("%d")とやった場合には、バイナリになります。
つまり、同じデータでも、そのデータを扱うプログラムによってテキストにもバイナリにもなりえます。
終わりがあるかどうかでバイナリ・テキストというのは一部の
データでは正しいと思いますが、全部にはあてはまりません。
まとめて大きなレベルで考えると、
基本的にはバイナリもテキストもなんら違いはまるっきりありません。
違いがあるのは、文字コード表と照らし合わせて翻訳して「人間にとって理解できる文字列」になるかどうかだけです。
まぁ一般的には「改行」があるかどうかですかね^^
だからこそ、
> 文字列はテキストでも、文字そのものはバイナリー。
ということになります。「1文字」という区切りは、弾も書いているように、例えば8bitを区切りとする、というように仕様で決められてるため、弾の定義の通り、バイナリーということになります。
なぜ「デミリタ」という言葉を使わなかったかは、デミリタ自体が存在しなくてただ単にブツ切れで「終わって」いる場合も含めたかったからでしょう。
私がこんな蛇足を書いてるのも、直前の方の書き込みが、非常に気になったからです。
printf("%d")でバイナリーになるって、二重の意味で間違ってませんか。
まず、整数と見なすべきデータは次の何ビットなのか、最初から仕様でわかってる時点でそのデータは「バイナリー」です。
一方、printf("%d")で出力されるデータは、何桁続くのかわからない、最後まで読んで(または最後がわかるように出力されて)初めて何桁で終わっているのかわかるという点で、テキストです。
バイナリは、聞けない。音声は、聞ける。
そんなこんなで、テキストはアナログなもので、バイナリはデジタルなものだと思います。
さぁ、デジタルとアナログの違いやいかに。
せっかくなので、そのWikipediaの箇所を弾さんなりに編集してもらえませんか?
# 私ではまだバイナリとテキストの違いについての理解が浅はかなので、編集し
# したらとんでもないことになりそうなので。