"BOKU"のITな日常

BOKUが勉強したり、考えたことを頭の整理を兼ねてまとめてます。

文字コードJISに2種類あること知らないとハマるよ/JIS7(ISO-2022-JP)とJIS8の話

f:id:arakan_no_boku:20191002201759p:plain

ユニコードUTF-8)に統一された環境で楽をしているおかげで忘れかけていた「文字コードの煩わしさ」に久々にどっぷりハマった経験をしたので、書いておきます。

 目次

文字コード「JIS」の固定長データの文字数カウントがおかしい 

文字コード「JIS」の固定長データをPCに取り込みたいが、うまくいかないという相談をうけました。

 

確認すると、データ長が指定より長い・・というエラーがでています。

じゃあ、データがおかしいのかと思い、データをエディタで開いて見直しても、問題はなく、指定の桁(文字)数に収まってます。

ところがプログラムで読み込むと指定の桁より6文字分長いと怒られる。

デバッグして変数をウォッチしてみると、確かに、文字数がセットされる変数に6文字多い文字数がカウントされてます。

データがおかしいのは間違いなさそうですが、エディタではわからない。

そういう類のエラーっぽいです。

エディタではわからないので16進ダンプで確認です

 

デバッグ出力を16進ダンプしてみました。

すると、元データの「半角カナ」文字があるあたりに怪しいところがありました。

こんな感じです。

1B 28 49 3B 38 57 32 39 5D 3C 5E 1B 28 42

この黒文字部分の「 3B 38 57 32 39 5D 3C 5E」が、半角カナ文字です。

その前後の赤文字部分「1B 28 49」と「1B 28 42」は、元のテキストには対応する文字がありません。

でも。

プログラムで6文字多くカウントされるのは、間違いなく、この6文字が犯人です。

しかも、自分はこの数字の並び・・どっかで見たことがあります。

結局、5分ほど眺めて・・思い出しました。

これは「エスケープシーケンスコード」です。

x0213.org

現象面だけを見ると、こういうことでした。

  1. 本来の固定長コードはエスケープシーケンスコードなしで作成されている。
  2. 取り込みプログラムもエスケープシーケンスコードを考慮していない。
  3. なのに、今回処理したデータにはエスケープシーケンスコードがはいっていた。

ということでエラーになっていた・・ということです。

とりあえずは、このエスケープシーケンスコードを取り除いてやると、エラーなく処理できました。

JISの固定長をエディタで上書き保存すると同じことがおきます

エスケープシーケンスコードのはいっていないJISの固定長データが、なぜ、エスケープシーケンスコードのはいったデータに変わってしまった原因は、オペミスです。

依頼した人が、「JISの固定長データ」に詳しくなかったのですね。

その人は外部機関から受け取った「JISの固定長データ」を、Windowsのエディタで開いて中身の確認をしたのです。

そして、つい「文字コードJIS」で上書き保存してしまったということでした。

もらったデータの文字コードは「JIS」で、保存した文字コードも「JIS」なので、なんら問題はないと思ったようですが、残念ながら違いました。

外部から受け取ったJISを、Windowsのエディタで開いて保存すると、こんな感じでエスケープシーケンスコードがはいりこんでしまうことがあるのです。 

JISには2種類あるのです

JISと呼ばれるものは大きく2つにわかれます。

ISO-2022-JP(JIS7)系とJIS8系です。

一番大きな違いは、ISO-2022-JP(JIS7)には、シフトイン、シフトアウトの考え方があることです。

www.ohsumap.jp

簡単に整理すると。

まず、「ISO-2022-JP」というのは、JIS7をベースに電子メールなどに使うために決められたものです。

JIS7の最大の特徴は、英大文字・小文字と半角カナのコードが重複していることです。

JIS7のエリアは元々半角カナなんて考慮せずに決められていたので足らないからです。

なので。

重複していても処理できるように、「ここからは半角カナとして使う」とか「ここからは英字として使う」という宣言によって、切り替えをするわけです。

その切替を示すコードのことを「シフトイン」「シフトアウト」と言います。

上記で「エスケープシーケンス」と書いたのも、それにあたります。

問題は・・ですね。

Windowsのエディタや文字コード変換ツールなどでJISを指定すると、この「ISO-2022-JP」が適用されるということです。

charset.7jp.net

さて。

ISO-2022-JPのそのへんの仕様は以下のように説明されてます。

ASCIIと漢字のコード範囲が重複するため、エスケープシーケンスによって切り替えます。

ESC $ @ 漢字の開始(旧JIS漢字 JIS C 6226-1978)

ESC $ B 漢字の開始 (新JIS漢字 JIS X 0208-1983)

ESC & @ ESC $ B 漢字の開始 (JIS X 0208-1990)

ESC ( B ASCIIの開始ESC ( J JISローマ字の開始

ESC ( I 半角カタカナの開始

この「半角カタカナの開始<ESC ( I>」は16進数だと「1B 28 49」です。

そして「ASCIIの開始<ESC ( B>」は「1B 28 42」です。

これでつながります。

つまり。

JISだから大丈夫と思って保存した際に、裏では「JIS(ISO-2022-JP)」に変換されて半角カナエリアの開始終了にエスケープシーケンスコードが6文字分セットされていたというわけなのです。

JIS8の半角英数カナはSJISと同じなんだな

 じゃあ、JIS8ってなんなのよ・・ということですが。

JIS8は半角カナにもちゃんとコードが割り当てて、シフトイン・シフトアウトのコードを挟まなくてもよくしたものと考えるとわかりやすいです。

固定長というのは、先頭から何文字目から何ケタ分・・みたいに意味付けをしますので、シフトイン・シフトアウトみたいな余分なものがはいってくると非常に具合がわるいわけですね。

とにかく。

JIS8なら余分なシフトイン・アウトコードが入らないので、固定長の桁を保証できる・・というのが重要なところで、だから、「JISの固定長」・・というのは、暗黙的に「JIS8の固定長」なのです。

今時、こんなこと知ってるのは、汎用機経験のある「高齢者」だけかもしれないなあ・・と思ったりもしますけどね。 

JIS8はSJISの1バイトコード部分と考えればいいんです

実は。

JIS8の「半角英数字」・「半角スペース」・「半角カナ」のコードはSJISと同じです。charset.7jp.net

 

www.asahi-net.or.jp

だから。

JIS8の固定長は普通に「SHIFT-JIS(SJIS)」で読めばよいわけです。

気づけば簡単なことなので、なんとかなりました。

でも。

やっぱり文字コードがからむとややこしいですね。

昔、汎用機全盛時は「EBICDIC」とか「JIS7」「JIS8」「EUC」「SJIS」などなど、常に文字コードを意識しながら仕事してたな・・と久々に思い出し、ユニコードがある現代は、ほんと良い時代だな。

そう思ったのです。

今回はこんなところで。

ではでは。