バイナリーエディタがあればファイルタイプが分かる!たぶん。

前回、自分が書いた記事は、緩すぎると一部から言われた東京Kです。こんばんは。
というわけで、少し技術寄りの話に戻して、よく分からないファイルの種類を特定するという話題でも。

先日「JPEGファイルのみを受け付けるシステムで、PNGファイルをアップロードできる原因調査」という事で、自分の所にまわってきたファイルがありました。

このように、実物を渡されたら、真っ先に疑うのが「そのファイルが本当に目的のファイルか?」です。
ファイルの形式を変えるために拡張子を変えるだけで良いと思っている方は、結構いらっしゃるので、まずはそこからの調査です。
調査方法は至って簡単で、バイナリーエディタでファイルの内容を見れば大体分かります。

と言うわけで、件のファイルを早速バイナリーエディタを開いて見たのがこちら:
PNGみたいなjpeg
「0xFF 0xD8」(以下、16進数での文字コードを便宜上Blogでは0xXXという形式で記載します)で始まっています。どう見ても、PNGではありません。
以上、トラブルシューティング終了!

・・・ではつまらないので、もう少し説明をします。

大抵のファイルは、ファイルの先頭にファイルの識別情報が書いてあるものです。
これを、ファイルヘッダー、または単にヘッダーと呼びますが、これがあるため、大抵のファイルはファイル名がどんなに変わっていても、バイナリーエディタ一つあればサクッと種類が確認ができます。

    • 「BM」で始まっているファイルはWindowsBitmap
    • 「%PDF」で始まって居るファイルはPDF
    • 「MZ」で始まって居れば、Windows用の何かしらの実行ファイル
    • 「PK」で始まって居れば、Zipかxlsxかdocxかwarかapkか・・・<略>(※1)

って感じです。
(※1)Zipファイルに特定のファイル名でデータを格納して、独自形式として使っているソフトが結構あるので「PK」だけでは用途がはっきりしない。

PNGファイルならば「0x89 0x50 0x4E 0x47」(文字コード0x89の1文字とPNGの3文字。)で始まりますが、今回は違います。

JPEGファイルは若干ややこしい構造をしていますが、上記画像で「JFIF」という文字列も見えますので、十中八九、JPEGファイルと言えます。
そこで、拡張子をJPEGに変更して、JPEGファイルの詳細を確認出来るソフトで開いてみると、撮影情報なども見れるので、JPEGファイル確定ということで、報告を作成して終了しました。

ところで、今回は残念ながらJPEGファイルでしたが、個人的にはPNGのヘッダーのギミックが好きです。

以下は、PNGファイルのヘッダーです。
正しいPNG
「0x89 0x50 0x4e 0x47 0x0d 0x0a 0x1a 0x0a」の8バイトではじまってますね。
実はこの、たった8バイトにはちょっとしたギミックが詰まっています。

0x89はASCIIコードで文字が存在しない文字コードですので、これにより、このファイルがテキストファイルでは無い事を暗に示しています。
続く0x50 0x4e 0x47は、PNGの3文字で、PNGファイルである事を示しています。

そして、0x0d 0x0aは、プログラマにはおなじみの改行コードですね。
この説明は後回しにして、続く0x1a。これは、テキストファイルにおいてファイルの終端を意味する制御コードです。
これにより、Windowsのコマンドプロンプトでテキストファイルの中味を表示するtypeコマンドでPNGファイルを開くと、次のようになります。

C:\>type Sample.png
臼NG

C:\>

(補注)日本語環境の場合、0x89 0x50はシフトJISの「臼」の字ですのでこのような表示になります。
(余談)個人的には、既に四半世紀も昔に流行って現在廃れている、Magファイルという画像ファイルが、このtypeコマンドのギミックを仕様の重要な位置に置いているので大好きだったりします。

そして、最後は0x0aでこれも改行コードですね。先ほどの改行コードは、CR-LFという種類の改行ですが、こちらはLFという種類の改行です。

なんで、PNGファイルヘッダー8バイトのうち3バイトも使って、これらの2つの改行があるのかというと、インターネット上でテキストファイルを転送するときには、受信したコンピューターの使用している改行コードに置き換えることがあります。
PNGファイルはバイナリファイルですが、うっかり、テキストとして転送すると、この仕組みにより、データが壊れてしまいます。
そこでPNGファイルは、ファイルヘッダー内にLFとCR-LFの2種類の改行コードを入れて、もしこれらが、LFまたは、CR-LFで統一されていれば、ファイルが正しく転送されてないと判断ができるという寸法です。

ここではPNGファイルのヘッダー仕様の最初の8バイトについて簡単に触れましたが、他のファイルのヘッダー仕様も千差万別で、なかなか勉強になります。
ヘッダーというものの沼に足を突っ込みたければ、まず第一歩としてBMPファイル(※2)の勉強がお勧めですので是非皆さんも。
(※2)WindowsBMPの32Bit色だとかなりシンプルでお勧めですが。24Bit色、16Bit色、8bit色になるにつれてギミックが増えていくしBITMAPCOREHEADERとかまで考え始めるとドツボにはまります。

ちなみに、真のバイナリニアンですと、ヘッダーが無くてもデータの並ぶパターンで、ファイル形式が判断できるらしいです。
壊れたデータを復旧する作業をされる方々ですが、彼らには頭が下がります・・・