(2021年2月6日)-g オプションを追加。
(2021年1月2日)40ビット以上のUnicodeで文字化けが起きる不具合を修正。
目次
サンプル・プログラムの実行例
たとえば
<img src="itaiji.php=?g=908A_E0109" /> は 邊 の異体字です。は 邊 の異体字です。
のようにして使うことができる。-gオプション のあとに、IVS(後述)を指定する。
サンプル・プログラム
itaiji.php | サンプル・プログラム本体 |
mji.00601.sqlite3 | MJ文字情報一覧表(SQLite3データベース) |
mji2sql.vbs | MJ文字情報一覧表(Excelファイル)からSQLite3データベースを生成するVBScript |
準備:MJ文字情報一覧表
だが、このAPIは試験的なものであり、2020年(令和2年)8月、文字情報基盤の成果物がIPAから一般社団法人文字情報技術促進協議会に移管したことから、停止する可能性がある。(2021年9月現在、利用できなくなっている)
そこで今回は、文字情報技術促進協議会に移管された「MJ文字情報一覧表」を利用することにする。
MJ文字情報一覧表は、前述の6万文字を超える漢字の一覧表である。
Strict Open XML形式のExcelファイルとしてダウンロードできるのだが、PhpExcel や Google Spreadsheet などの既製ライブラリを使ってオープンすることができない。Excelも2007ではオープンできず、Microsoft 365 を使ってオープンできることが分かった。
そこで、ダウンロードしたMJ文字情報一覧表を、Microsoft 365 を搭載したPC上で VBScript を使って読み込み、SQLite データベースに変換し、PHPから利用できるようにする方針を立てた。
SQLite データベースを生成するため、SQLite ODBCドライバを用意する。
公式サイトから SQLite ODBC Driver をダウンロードする。64ビット版でも、32ビット版の "sqliteodbc.exe" をダウンロードし、インストールするといいようだ。
Microsoft 365 と SQLite ODBC Driver が用意できたら、次の手順で MJ文字情報一覧表をデータベースに変換する。
- MJ文字情報一覧表をダウンロードし、解凍する。"mji.00601.xlsx" という約7.5Mバイトのファイルができる。
- 同梱のVBScript "mji2sql.vbs" を実行する。MJ文字情報一覧表ファイルは変数 fnameMJ に、SQLiteデータベース・ファイルは DBname にフルパスで記述すること。DBname は書き込み権限があるパスを指定する。
- しばらくすると、SQLiteデータベース・ファイルができる。PHPから参照できるフォルダへ移動する。
MJ文字情報一覧表:テーブル定義
mj:MJ文字情報一覧表 | |||
---|---|---|---|
No. | 名前 | 型 | 内容 |
1 | MJcode | テキスト | MJ文字図形名 |
2 | ucs | テキスト | 実装したUCS:プライマリキー |
3 | ivs | テキスト | 実装したMoji_JohoコレクションIVS |
4 | koseki | テキスト | 戸籍統一文字番号 |
5 | juki | テキスト | 住基ネット統一文字コード |
6 | sesaku | テキスト | 漢字施策:常用漢字、人名漢字 |
1 | yomi | テキスト | 読み(参考):音読みは片仮名、訓読みは平仮名。 |
準備:IPAmj明朝フォント
文字情報技術促進協議会からダウンロード、解凍すると、"ipamjm.ttf" という約46M バイトの巨大なフォントファイルが取り出せる。
これを、PHPから参照できるフォルダに配置する。
解説:初期値
  37: //入力文字(デフォルト)
  38: define('DEF_SOUR', '邊');
  39:
  40: //MJ文字情報一覧表(SQLiteデータベース)
  41: define('DBFILE', './mji.00601.sqlite3');
  42:
  43: //検索SQL(※変更不可)
  44: define('PRE_SELECT', 'SELECT MJcode, ivs FROM mj WHERE ucs=:ucs;');
  45: define('PRE_SELECT_IVS', 'SELECT MJcode, ivs FROM mj WHERE ivs=:ivs;');
  46:
  47: //PNG画像データURL
  48: //define('URL_PNG', 'https://mojikiban.ipa.go.jp/');
  49: define('URL_PNG', 'https://moji.or.jp/mojikibansearch/img/MJ/');
  50:
  51: //IPAmj明朝フォント・ファイルの場所
  52: define('IPAmj', '../../../../common/font/ipamjm.ttf');
解説:Unicodeコードポイントを求める
 214: /**
 215: * Unicodeコードポイントを求める
 216: * @param string $ch 1文字
 217: * @return string Unicodeコードポイント
 218: */
 219: function ch2ucp($ch) {
 220: return sprintf("U+%0X", hexdec(bin2hex(mb_convert_encoding($ch, 'UCS-4', INTERNAL_ENCODING))));
 221: }
解説:UnicodeコードポイントからUTF-8文字を求める
 223: /**
 224: * UnicodeコードポイントからUTF-8文字を求める
 225: * @param string $ucp Unicodeコードポイント
 226: * @return string UTF-8文字
 227: */
 228: function ucp2ch($ucp) {
 229: $ch = '';
 230: if (preg_match('/U\+([0-9A-F]+)/ui', $ucp, $arr) > 0) {
 231: $bin = hex2bin(str_repeat('0', 8 - strlen($arr[1])) . $arr[1]);
 232: $ch = mb_convert_encoding($bin, INTERNAL_ENCODING, 'UCS-4');
 233: }
 234: return $ch;
 235: }
解説:コードポイントから異体字を求める
 237: /**
 238: * 異体字を求める:コードポイントから
 239: * @param string $ch 1文字
 240: * @param array $items 情報を格納する配列
 241: * @return int 異体字の数/0:指定文字が見つからない/(-1):DBアクセスに失敗
 242: */
 243: function geiItaiji($ch, &$items) {
 244: $ucp = ch2ucp($ch);
 245:
 246: //MJ文字情報一覧表(SQLiteデータベース)検索
 247: try {
 248: $pdo = new PDO('sqlite:' . DBFILE);
 249: $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 250: $stmt = $pdo->prepare(PRE_SELECT);
 251: $stmt->bindValue(':ucs', $ucp, PDO::PARAM_STR);
 252: $stmt->execute();
 253: $cnt = 0;
 254: while ($row = $stmt->fetch()) {
 255: //画像ファイルのURL
 256: $items[$cnt]['png'] = URL_PNG . $row['MJcode'] . '.png';
 257: //HTMLエンティティ
 258: if (preg_match('/([0-9A-Z]{4,6})\_([0-9A-Z]{5})/ui', $row['ivs'], $arr) > 0) {
 259: $items[$cnt]['itaiji1'] = '&#x' . $arr[1] . ';&#x' . $arr[2] . ';';
 260: } else if (preg_match('/U\+([0-9A-Z]{4,6})/ui', $ucp, $arr) > 0) {
 261: $items[$cnt]['itaiji1'] = '&#x' . $arr[1] . ';';
 262: } else {
 263: $items[$cnt]['itaiji1'] = '';
 264: }
 265: //HTMLエンティティ(エンコード)
 266: $items[$cnt]['itaiji2'] = preg_replace('/&/ui', '&', $items[$cnt]['itaiji1']);
 267: $cnt++;
 268: }
 269: $pdo = NULL;
 270: } catch (PDOException $e) {
 271: $cnt = -1;
 272: }
 273:
 274: return $cnt;
 275: }
解説:IVSから異体字を求める
 277: /**
 278: * 異体字を求める:IVSから
 279: * @param string $ivs IVS
 280: * @param array $items 情報を格納する配列
 281: * @return int 異体字の数/0:指定文字が見つからない/(-1):DBアクセスに失敗
 282: */
 283: function geiItaijiIVS($ivs, &$items) {
 284: //MJ文字情報一覧表(SQLiteデータベース)検索
 285: try {
 286: $pdo = new PDO('sqlite:' . DBFILE);
 287: $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 288: $stmt = $pdo->prepare(PRE_SELECT_IVS);
 289: $stmt->bindValue(':ivs', $ivs, PDO::PARAM_STR);
 290: $stmt->execute();
 291: $cnt = 0;
 292: while ($row = $stmt->fetch()) {
 293: //画像ファイルのURL
 294: $items[$cnt]['png'] = URL_PNG . $row['MJcode'] . '.png';
 295: //HTMLエンティティ
 296: if (preg_match('/([0-9A-Z]{4,6})\_([0-9A-Z]{5})/ui', $row['ivs'], $arr) > 0) {
 297: $items[$cnt]['itaiji1'] = '&#x' . $arr[1] . ';&#x' . $arr[2] . ';';
 298: } else if (preg_match('/U\+([0-9A-Z]{4,6})/ui', $ucp, $arr) > 0) {
 299: $items[$cnt]['itaiji1'] = '&#x' . $arr[1] . ';';
 300: } else {
 301: $items[$cnt]['itaiji1'] = '';
 302: }
 303: //HTMLエンティティ(エンコード)
 304: $items[$cnt]['itaiji2'] = preg_replace('/&/ui', '&', $items[$cnt]['itaiji1']);
 305: $cnt++;
 306: }
 307: $pdo = NULL;
 308: } catch (PDOException $e) {
 309: $cnt = -1;
 310: }
 311:
 312: return $cnt;
 313: }
参考サイト
- 外字が不要に――ISO/IEC 10646:2017:ぱふぅ家のホームページ
- MJ文字情報一覧表:文字情報技術促進協議会
- IPAmj明朝フォント:文字情報技術促進協議会
そこで今回は、ISO/IEC 10646:2017の異体字を表示するPHPプログラムを作ってみることにする。