ぺんぎんらぼ

お笑いとマンガ好きなしょぼしょぼWeb系エンジニアの日記です。たまに絵を描きます。

お笑いとマンガ好きなしょぼしょぼWeb系エンジニアの日記です

いくつになっても「データと文字」を理解できない自分へ①

f:id:penguinlabo:20200210195333p:plain

自分が何となく使っている技術要素についてきちんと勉強しなおして、いざという時フレッシャーの方などに説明できるようにまとめることにしました。

第一弾としてこの記事ではJavaに限らずコンピュータの世界一般にいえる「ファイルデータと文字」についてまとめてみました。

ファイルの種類は大きく2種類しかない

f:id:penguinlabo:20200206161154p:plain

コンピュータでは色んな "ファイル" を扱いますが、「ファイルの種類」といったとき一番最初に思いつくのが、ファイルの拡張子やプロパティではないでしょうか。 例えば、MS-Officeのエクセルファイルであれば「ファイルの種類」は上のように「Microsoft Excel ワークシート (.xlsx)」と表示されます。

「ファイルの種類」はこれ以外に、Javaのソースファイルだったり、動画ファイルだったり、さらに動画ファイルにしても「MP4形式の動画ファイル」だったり、「WMV形式の動画ファイル」だったりと多岐にわたります。
ひと口に「ファイルの種類」といっても、どの粒度で見るかによって、「ファイルの種類」は変わってきます。

ただし下の図の通り、
一番大きく分類したときの「ファイルの種類」は「テキストファイル」「バイナリファイル」の2種類しかありません。 Javaでも、ファイルIO処理を扱う時、いったんこの2種類のどっちになるかを考えてファイルを扱います。

f:id:penguinlabo:20200206163020p:plain

「テキストファイル」と「バイナリファイル」の違い

メモ帳で開いて文字として表示されるファイルが「テキストファイル」、文字化けしたら「バイナリファイル」

これが鉄則です。

では、なぜメモ帳でテキストファイルは開けて、バイナリファイルは文字化けするのか?

ファイルはバイトという単位の数値の集まりです。そして、その数値の一部に文字が割り当てられています。

メモ帳がファイルを開くときどういう動きをしているかというと、メモ帳はファイルを数値として読み取って、その数値に割り当てられた文字を表示しています。

例えば、ファイルから読み取った数値が65だった場合、65という数値に割り当てられている「A」という文字を表示しています。

ここで重要なのは、文字が割り当てられている数値は一部だけということです。
例えば、数値の65には「A」という文字が割り当てられていますが、数値の5には文字が割り当てられていません。
メモ帳は、文字が割り当てられていない数値を読み取ったときに正しく表示できずに文字化けを起こします
テキストファイルは文字が割り当てられている数値だけで構成されていますが、バイナリファイルは文字が割り当てられていない数値も含まれています。だから、メモ帳でバイナリファイルを開くと文字化けをするのです。

バイトデータ

コンピュータの中は「バイトデータの集まり」でできています。
ファイルは「バイトデータの集まり」をディスクに記録したものだし、
実行してるプログラムは「バイトデータの集まり」をメモリに乗っけたものだし、
パソコンのモニタに表示されている画面だって「バイトデータの集まり」を画像として表示したものです。

だから、あらゆるファイルの実体は、「バイトデータの集まりをディスクに記録したもの」です。

では「バイトデータ」とはなにか。
「バイト」はそもそも数値の単位です。1バイトで表現できる数値は10進数でいうと0~255の範囲で、16進数だと00~ffの範囲になります。

このことから、「バイトデータの集まり」は「00~ffの数値の集まり」となります。
ここが非常に大事なところです。

以降は「ファイルは00~ffの数値の集まりである」ということを常に念頭において読み進めてください。

コンピュータでは、このバイト「00~ffの数値」一つ一つに文字が割り当てられています。
※ここでは、アスキー文字(いわゆる半角英・数・記号文字を表せる文字)に限定して話をします。「アスキー文字」って何かという話はいったん置いておきます。

次の図が、各数値に割り当てられている文字です。たとえば、16進数で「34」は文字「4」になり、「4b」は文字「K」になります。 LOVEという文字データをバイトデータで表せば、「4c 4f 56 45」になるんですね。

f:id:penguinlabo:20200206180020p:plain

ところで、「00」~「1f」、「7f」には2~3文字のアルファベットが記載されていますが、これはどういう意味かというと、文字以外の「機能」が割り当てられています。
テキストファイルには文字以外に「タブ」と「改行」が含まれますが、「タブ」機能が割り当てられている数値は「09」、「改行」機能が割り当てられている数値は「0a」と「0d」です。
つまり、「バイトデータ「00」~「ff」のそれぞれの数値には、「文字」か「機能」のいずれかが割り当てられている」ということですね。 ※また、この表には「80」~ffがありませんが、アスキー文字では、この領域に文字が割り当てられていないためです。

  • 20~7e = 「文字」への割り当て
  • 09、0a、0d = タブ、改行「機能」への割り当て

よって、テキストファイルは、割り当て表で赤枠で括られている、09、0a、0d、20~7eの数値のみで構成されたファイルになります。
換言すれば、「テキストファイルは「文字」と「改行」、「タブ」にあたる数値の集まりである」といえます。

ここまでのまとめ

テキストファイルとバイナリファイルの定義

ファイル形式 定義
テキストファイル 文字と改行、タブに割り当てられた数値のみの集まり
バイナリファイル 文字と改行、タブに割り当てられた数値以外も含む数値の集まり

なぜ、アプリは動くのか

アプリケーションは「バイナリファイル」の一種で、「実行可能ファイル」に分類されます。
「実行可能ファイル」もファイルなので、中身は「00~ffの数値の集まり」です。数値の集まりがなぜ、プログラムとして動くかを説明します。
今回の主題からは外れる内容なので、興味のない人は読み飛ばしてください。

コンピュータでは、バイトデータである「00~ffの数値」に文字が割り当てられていることを説明しました。先ほど挙げたアスキーコード表が対応表になります。
しかし、コンピュータは、バイトデータである「00~ffの数値」には別の意味も持ちます。数値ごとに「CPU命令」が割り当てられています。「CPU命令」は「最小単位の処理」と読み替えても構いません。Windowsが動作するintelの8086アーキテクチャでは、以下のように数値に対応する「CPU命令」が割り当てられています。

f:id:penguinlabo:20200206203322p:plain

例えば、テキストデータで16進数の「21」は記号の「!」を表しますが、バイナリファイルの実行可能ファイルでは「AND EW,GW」という命令をCPUが実行することになります。

アスキー文字以外も考える

ここまで説明しましたが、当然テキストファイルには、半角英数のアスキー文字以外に、私たちの使う日本語ひらがなや漢字、全角アルファベット・数値・記号、半角カタカナなどが含まれることがあります。
これらの文字も考慮するとなると、テキストファイルの定義が一気に難しくなります。。。

かなり複雑になるので、ここらへんはまた次回に!