文字コードの最近のブログ記事

一昨日のことですが、中国・四国地方から文字化けのニュースがありました。IT系のメディアではなくNHKです。

Jアラートとは「全国瞬時警報システム」なのだそうで、最近北朝鮮のミサイル発射の問題のニュースに出てくることがあります。この緊急情報の送受信訓練で、メールでテスト電文を配信したところ文字化けして読めないものだったというニュースです。

上記リンク先には画像があり、携帯端末上で文字化けした文面が写っています。ぱっと見た感じでは、UTF-8のテキストをシフトJISとして解釈しようとしたように見えますが、冒頭の「発表」と末尾の「しまね防災情報」は見えています。前後の定型文がシフトJISで用意されていて、間に挟む本文もシフトJISでなければいけないところにUTF-8のバイナリを入れてしまったといった可能性が考えられます。

まあ、訓練で問題が見つかったのだから良かったとはいえるでしょう。プログラム自体は変えていなくても、そこに外部から与えるデータとして元々の想定とは異なるものを入れてしまったということもあり得るので、通しでやってみるのは重要なことです。

それにしてもIT系でない一般のニュースで「文字化け」という言葉を見るのはなかなか感慨深いものがあります。これをきっかけに拙著『プログラマのための文字コード技術入門』にも注目が集まる......かな?

ユーモラス、と言っていいのか分かりませんが、興味深いニュース記事がありました。

この記事の伝えるところによると、「「任●(にんきょう)団体山口組」(●は「侠」の旧字体)が、組織名を「任侠(にんきょう)山口組」に変更する通達を流していた」のだそうです。その理由として、「表記される際、「侠」の旧字体が正しく表記されないケースがあったことに不満を募らせたとみられる」と書かれています。

「「侠」の旧字体」は、当ブログ記事の題にあるように「俠」です。この字はJIS第3水準、面区点番号1-14-26にあります。人名用漢字にも入っています。

SKKの第3第4水準漢字辞書では「にんきょう」から「任俠」に変換できます。Macでも入力できます。もうこうした第3第4水準を避ける必要はないでしょう。

UTF-8のようなUnicodeの符号化方式で扱えるのはもちろん、JIS X 0213の符号化方式、EUC-JIS-2004Shift_JIS-2004で問題なく符号化できます。PythonやPHP, libiconvなどのコード変換はこれらの符号化方式に対応しています。

もっとも、上記のリンク先でもいまだに「●は「侠」の旧字体」のような読みにくい注釈を施しているのは残念なことです。JIS X 0213の全ての文字を扱えることがこれからの日本語処理の必須条件だという硬派な思想でビシッと筋を通して、第3水準漢字の組織名をいつでもどこでも使えるようにするのが良いのではないかと思います。

Java 9では国際化機構で用いられるリソース文字列のファイル表現の文字コードとしてUTF-8がデフォルトで使用されることになるそうです。従来、ISO/IEC 8859-1がデフォルトであるためにUnicodeエスケープが必要となり、外部ツールで日本語テキストを「\u3042」のようなエスケープ文字列に変換する煩わしさがありましたが、ようやく解消されることになります。

Javaには古くから国際化のための枠組みが用意されています。その最も基本的な機構となる、多言語のメッセージ文字列を用意する仕組みとしては設定ファイルなどに用いるプロパティファイルという形式が用いられています。ところがこのファイルはデフォルトの文字コードがISO/IEC 8859-1という西欧向けの1バイトコードなのでした。

このため、JDKではnative2asciiというツールが提供されて、Shift_JISやEUC-JP等の文字コードからUnicodeエスケープを用いる形式に変換できるようにされていました。また統合開発環境のEclipseにはプロパティエディタというプラグインが開発され、コマンド操作なしにあたかも直接漢字を記述できるかのような操作が可能になっています。とはいえリソースファイル自体はもちろんUnicodeエスケープなので、普通のテキストエディタで表示すると欧文以外は全く読めないものになります。

Javaのプロパティファイル自体はUTF-8で記述されても読み込めるように既になっていたのですが、その重要な用途である国際化のリソースファイルとして読み込むResourceBundleクラスではなぜかISO/IEC 8859-1がデフォルトという状態が長く続いていました。実は自分でクラスを定義して一工夫してやるとUTF-8にできるという裏技(?)もあったりしたのですが、そういうのはデフォルトで提供してほしいものです。(この辺のことは拙著『プログラマのための文字コード技術入門』第7章に記しています)

オープンソースのWebアプリケーションフレームワークであるPlay Frameworkではリソースファイルにわざわざ別の仕組みを用意してUTF-8で直に書けるようにしています。リソースファイルがもっと早くUTF-8で符号化できるようになっていたらこのような措置はとられれなかったかもしれません。

遅きに失した感はあれども、ともかく改善されることになって良かったです。

Unicode 10.0が2017年6月20日にリリースされました。今回は8,518文字が追加されています。

日本語話者にとって最も関係しそうなのは変体仮名の導入でしょう。

変体仮名とは

現在、平仮名は1音につき1文字ですが、以前は同じ音に対して複数の書き方がありました。例えば、平仮名の「か」は漢字「加」が元になっているもので、これ以外に「か」と読む平仮名はありませんが、かつては「可」を元にした仮名も使われていて同じく「か」と読まれました。そうした複数のバリエーションがあった仮名を明治時代に標準化したものが今の平仮名です。このとき採用されなかった異体が変体仮名と呼ばれるものです。

変体仮名は今日では文章を綴るのには使われませんが、そば屋の看板などで装飾的に用いられることがあります。

Unicodeにおける変体仮名

変体仮名はUnicodeではBMPでなく面01に配置されました。U+1B000-1B0FFのKana SupplementブロックおよびU+1B100-1B12Fの Kana Extended-Aです。例えば先ほど例に挙げた「可」に基づいた「か」は符号位置U+1B019にあり、文字名はHENTAIGANA LETTER KA-3とされています。読みを「KA」のように示して、複数ある異体は数字で区別されています。全部で285文字の変体仮名が収録されています。

符号化の方式としては、単純にひとつの符号位置にひとつの文字が対応する形になっています。複数の読まれ方をする字がありますが(例えば「惡」に基づく字、「あ/を」)、こうしたものもひとつの符号位置にのみ置かれ、読みが違うからといって重複して配置されてはいません。標準化の途中の段階では、音価に相当する符号位置を与えて異体字セレクタのようなもので変種を示すといった案もあったようですが、最終的には扱いやすい形式に落ち着いたことになります。

漢字の追加も

今回、CJK統合漢字拡張Fが追加されています。7,473文字と結構大きな追加です。使う機会があるかどうかはまた別の話ですが......。

拡張Fのコード範囲は2CEB0-2EBE0となっています。

Pythonとlibiconv, nkf, Javaのコード変換を比較した記事がありました。

ASCIIとJIS X 0201の違いに起因する円記号問題とチルダ・オーバーライン問題、それにUnicodeのFTPサイトが原因と思われる全角ダッシュの件という既知の問題が多いので目新しくないのですが (『プログラマのための文字コード技術入門』をお読みいただければわかります)、Pythonについて目新しげな話がありました。

Pythonでは他と違って、二重(白抜き)の括弧をU+FFxxの位置にあるものでなくU+29xxに割り当てているそうです。うむ。そうか、そうきたか。

JISの公式な対応表ではU+FFxxの方になっています。文字名でいうとFULLWIDTH {LEFT|RIGHT} WHITE PARENTHESISです。

ただ、ここで「なぜFULLWIDTHなのか」という疑問を持った方もいるでしょう。本来UnicodeのFULLWIDTH/HALFWIDTH云々というのは、シフトJISのように1バイトコードと2バイトコードとの間で重複符号化のある符号化方式との往復変換の救済用に設けられたものです。ところがこの括弧記号はJIS側の符号化方式(Shift_JISやEUC)で重複符号化されているものではないので、本来FULLWIDTHになるきちんとした理由はありません。にもかかわらず、UnicodeにJIS X 0213の文字を追加する作業でなぜかFULLWIDTHの方に入れてしまいました。

一般に用いられている変換表は、(多少ヘンだと思ったかもしれないにせよ)このUnicodeの作業を反映したものになっています。JIS X 0213の追補1でもそうなっています。Pythonのような判断をしたものは私はほかに見たことがありません。

Pythonがこうしたのは、強い信念のもとでの判断なのか、そうでなく何か行きがかり上そうなっただけなのか、ちょっと興味を惹かれるところではあります。

UnicodeにはのちにU+2E28, 2E29に{LEFT|RIGHT} DOUBLE PARENTHESISというのが追加されて(バージョン5.1らしい)、どうもこっちがいいんじゃないかという気もしてくるのですが、後から出してこられるのはつらい。3.2の時にあれば良かったのですが。

ちなみにこの二重の括弧は、文章や辞書において文中に入れる注記の類に用いられることのある記号です。

【追記 2017年6月7日】 JISとUnicodeの間のコード変換表はこちらから入手できます。JISの公式な定義と同等です: JIS X 0213のコード対応表

北海道南部の松前町は、20世紀日本の書家・金子鷗亭の出身地であり、その影響で書道教育の盛んな町として知られています。

その松前で高校生の書道パフォーマンスの大会が開催されたニュースがありました。

上記のうち、函館新聞の方は記事の中にちょっと残念な部分があります。書家の名前が「金子鷗亭」と、「鷗」の字がHTMLの文字参照になってしまっています。40407は16進表記で9DD7にあたります。UnicodeでU+9DD7は第3水準漢字「鷗」の符号位置です。

人手で40407のような数字を入力したとは考えにくい。私の想像ですが、テキストエディタなどで「鷗亭」と入力したあとで、工程上の何らかの段階でシフトJISに変換することがあったのではないでしょうか。その際に、第3第4水準漢字まで対応しているJIS X 0213Shift_JIS-2004ではなく、第1第2水準までしか対応していないJIS X 0208ベースのShift_JIS (ないしはその誤った実装であるCP932) に変換しようとして、このような結果になったのではないか。

SJISとの変換が必要な時には、Shift_JIS-2004 ないしは Shift_JISX0213 を指定すれば、こうした問題は起きなくなります。Python, PHP, Java, libiconv等を用いるとUTF-8とShift_JIS-2004との間でコード変換ができます。

この鷗(かもめ)という字は、常用漢字には入っていませんが、人名用漢字には入っています。文化的な分野ではこの金子鷗亭や森鷗外といった人名に使われますし、白鷗大学 (栃木県) という大学名や鷗島 (北海道江差町) といった地名にもあります。いつでも使えるように、第3第4水準漢字に対応した符号化方式 (第3第4水準文字コード) を常に用いることが肝心です。

なお、上記ニュース記事のもう片方、毎日新聞の方では、「鴎」という略字体を使っています。これはJIS X 0208の1983年改正で大きく字体の変えられたものとして有名ですが、元は新聞による使用の方が83JISよりも先だったのだそうです。その意味では、新聞がこの略字を使うのは一貫していると言えなくもない。ただ、表外字の部分字体にも略字体を適用しようとするなら鴎の一字だけでなく全ての表外字が対象になるのか、そうでないのなら鷗が適用対象になる理由は何なのかと、方針がなかなか難しくなってくるので、元来の字体 (鷗) にあわせるのが無難であろうと思います。

GNU libiconvはJIS X 0213の符号化方式、Shift_JIS-2004 (Shift_JISX0213) や EUC-JIS-2004 (EUC-JISX0213) に対応していますが、コマンドを実行した際にこれらが入っていない場合もあり得ます。入っているかどうかはiconvのコマンドラインオプション --list で確かめられます。

これらの符号化方式に対応するには、ビルドする際にconfigureのオプション --enable-extra-encodings を指定しておく必要があるようです。インストールされているiconvコマンドでShift_JIS-2004が使えないときはこれが指定されていなかった可能性があります。もしこれらの符号化方式が入ってなかったら、管理者に相談するか、そうでなければ、自分でソースをダウンロードして上記のオプションを用いてビルドしてみるのもいいでしょう。

SJISやEUCと変換するときは常にShift_JIS-2004, EUC-JIS-2004を使いたいので、これらに対応した iconv コマンドを用意しておきたいものです。

参考: GNU libiconv

「2バイト文字」という言い方につっこみをしている人をあるところで見かけたので、これについて少々。

漢字や平仮名を「2バイト文字」のようにいう語法はずっと前からあります。昔からあるのだからいいのかというと、むしろこれは昔だからこそ便宜的に通用した言い方で、今では不適当です。順を追って説明します。

「何バイト」は文字そのものの性質ではない

まず、根本的なこととして、ある1文字の符号化表現に何バイトを要するかは、文字それ自体の属性ではなく、用いる文字コード (コード系) に依存することです。

例えば片仮名の「ア」を符号化するのに必要なバイト数は、JIS X 0201なら1バイト、JIS X 0213なら2バイト、UTF-8なら3バイト、UTF-32なら4バイトと様々に異なります。割り算の記号「÷」は、ISO/IEC 8859-1では1バイト、JIS X 0213では2バイト、UTF-32なら4バイト。

昔はあまり気にしなくてよかった

ただ、昔はそういう面倒なことを言わずに済んだのは、日本ではASCII/JIS X 0201とJIS X 0208だけを考えていれば良かったためです。これなら「漢字は2バイト文字」のような言い方で良かった。1バイトコードと2バイトコードを混在させると英数字や片仮名に1バイトと2バイトの両方が出てきますが、前者を「半角」後者を「全角」と呼ぶことであたかも別の文字のような扱いをすることで乗り切ってきた。

そういう牧歌的な時代が過ぎて、Unicodeが出てきたりまた8859など他の文字コードも意識するようになると、「どの文字コードの話をしているのか」をはっきりさせないと「何バイト」ということはいえなくなったわけです。

特定のコード系についての話ならOK

もっとも、逆に言えば、例えばShift_JIS-2004といった特定のコード系を前提とした場面では、「2バイト文字」とか「1バイト片仮名」といった言い方は全然アリです。

まとめ

  • 漢字や平仮名といった (コード系とは独立な) 文字種のつもりで「2バイト文字」というのは不適当。ある文字が何バイトかは用いるコード系による。
  • 特定のコード系を前提とした場面で、その系における1バイト文字、2バイト文字、のような言い方はOK。
  • なぜ昔はそういう煩わしいことを気にせずに済んだかというと、ASCII/JIS X 0201とJIS X 0208しか対象としていなかったから

関連記事

すごい後知恵なんですが、1980年代に「EUC」方式の文字コードをISOで国際標準化しておけば良かったのではと考えます。

EUC方式、というのがどういうことかというと、

  • 8ビット符号表のGL領域(0x20-0x7F)にASCIIを配置、
  • GR領域には2バイトの漢字コードを配置

という形が基本で、必要に応じてシングルシフトコードでG2, G3に指示されている2バイト(ないし1バイト)符号化文字集合をGRに呼び出せるステートレスな符号、というものです。

具体的には、EUC-JIS-2004, EUC-JP, EUC-KR, EUC-CNなどです。

これはISO/IEC 2022の枠内の運用なので、別段この方式を改めて標準化する必要はないのではないか、という意見もあるでしょう。しかし、型決めしておくことによるメリットもあります。理解が容易になり、設計や実装も使い回せる。特に2022は複雑ですからね。

ISO/IEC 8859という規格は、GLにASCII、GRに欧州等の各地域ごとの文字集合を配置した1バイトコード、という形になっています。この2バイト版があっても良かったのではないか。

それは世の中で「EUC」と呼ばれてそれなりに共有されているのだけども、ISOで標準化されていなかったのはもしかすると惜しかったのではないか。特に、2バイトコードが出てきた早いうちからそれがあれば......、と考えた次第です。

日経新聞のサイトに気になる題の記事が載っていました。

私は飲むとすぐ赤くなる方なので読んでみたのですが、異なる方面で発見がありました。通常JIS第3水準漢字で表記される単語が使われていたのです。

酒皶という言葉

記事の途中に、「鼻や頬の一部が飲んでいないときでも赤くなる症状を「酒さ」(しゅさ) と呼ぶ」とあります。この記事では平仮名にしていますが、漢字では「酒皶」と書きます。この「皶」という漢字はJIS第3水準、面区点番号1-88-70です。

なぜそんなことを知っているかというと、以前にも見覚えがあるからです。ブログ記事にもしています。

この記事では、『皮膚の医学 肌荒れからアトピー性皮膚炎まで』 (田上八朗著、中公新書) という本に出てきたのを取り上げていました。

この言葉は国語辞典の大辞林や広辞苑にも出てきます。第3水準漢字を使った「酒皶」という漢字表記も載っています。ちなみに広辞苑はこの酒皶という症状について「酒客に多いが飲酒と無関係にもおこる」としています。

病気や医学といった分野にも第3第4水準漢字は時々現れるのです。

文字入力とコード変換

この酒皶という単語は、Emacsで動作する文字入力プログラムSKKの第3第4水準辞書に入っていますから、SKKでは辞書ファイルとしてSKK-JISYO.JIS3_4を参照していれば、何も特別な操作なしに「しゅさ」という読みから変換できます。

文字コードとしてはUTF-8やShift_JIS-2004, EUC-JIS-2004などで扱えます。JIS X 0208ベースのShift_JISなどでは符号化できないので、SJISにコード変換する場合は下記のようにiconvコマンドでShift_JIS-2004 (Shift_JISX0213) を指定すれば文字化けせずにうまくいきます。

  iconv -f UTF-8 -t SHIFT_JISX0213 < utf8.txt > sjis.txt

最近のブログ記事

書家の第3水準漢字:「金子鷗亭」
書家・金子鷗亭の作品の特別展が北海道立函…
福原愛選手の結婚会見に見る台湾の言語事情、そして第3水準漢字
台湾語を使った結婚会見 リオ五輪でも活躍…
『アイヌと縄文』の第4水準漢字:「埦」
瀬川拓郎『アイヌと縄文: もうひとつの日…
札幌で見たJIS X 0213の文字
札幌の中心部、大通公園と札幌駅を地下でつ…
Pokémon GO の JIS X 0213の文字
その字はJISにある スマホゲームのPo…

広告