JISコードによる入力可能文字の判定(第1水準、第2水準、第3水準、第4水準、半角文字など)

他のシステムにデータ連携を行う場合などに、文字化けを起こさないよう入力文字のチェックを行う場合があります。


今回は、JISコードを使って入力可能文字の判定処理を整理したいと思います。


まず、JISコードの体系ですが「区点番号」という番号体系で文字コードが付与されています。2バイト文字の場合、上位バイトが区、下位バイトが点となっています。区毎に94の点で構成されており、区単位で設定される文字が決まっています。

  • 01区 記号
  • 02区 記号
  • 03区 英数字
  • 04区 ひらがな
  • 05区 カタカナ
  • 06区 ギリシア文字
  • 07区 キリル文字
  • 08区 罫線素片
  • 16〜47区 第一水準の漢字
  • 48〜83区 第二水準の漢字


これらのJIS漢字コードについての詳細な説明は以下のサイトで確認してください。


JIS漢字コード:JIS第一・第二水準
http://www.shuiren.org/chuden/teach/code/main4.htm


文字コード
http://charset.7jp.net/jis.html


ということで、入力チェックを行うためには画面上で入力された文字を一旦 Unicode から JIS にエンコードし 区点 を確認した上で判定を行います。


JISエンコーディングiso-2022-jp を使用します。(iso-2022-jp は、JIS X 0208 第二水準までの漢字をサポートしています。)

  byte[] byteData = System.Text.Encoding.GetEncoding("iso-2022-jp").GetBytes(testChar);


上記のコードでUnicode文字を1文字ずつバイト配列に変換すると、2バイト文字の場合は 8 バイトのバイト配列が返ってきます。これは、漢字シフトコードが付与されるためで、先頭に 27 36 66 (1B 24 42) の3バイト、末尾に 27 40 66 の3バイト(1B 28 42)が追加されます。そのため3バイト目が区、4バイト目が点になります。01区が33(21)、01点が33(21)から始まるので、それぞれを区点に変換するには32を減算します。()は16進数。

  if (byteData.Length == 8)
  {
    // 2バイトコード
    Ku  = byteData[3] - 32;
    Ten = byteData[4] - 32;
  }


制御文字や英数字などの、1バイト文字コードについてはJISエンコーディングしても1バイトで返ってきます。こちらはASCII文字コードと同じなので、制御文字をエラーとする場合は32-126(20-7E)以外の範囲はエラーにします。

  if (byteData.Length == 1) 
  {
    // 1バイトコード
    if !((byteData[0] >= 32) && (byteData[0] <= 126))
    {
      isError = true;
    }
  }


注意点ですが、半角カナをJISエンコーディングすると全角カナの文字コードが返ってきます。半角カナをエラーとする場合は、あらかじめ半角カナを定義しておき、該当する場合はエラーとするようにします。

string hankakuKana = @"ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン";
if(hankakuKana.Contains(testChar)
{
  //半角カナ
  isError = true;
}

最後に第三水準と第四水準の判定です。


これらの文字は JIS X 0213:2000 で追加された文字ですが、iso-2022-jp ではサポートされていないため変換して区点情報を取得することができません。(Windowsでは、これらの文字はJISではなくUnicodeとしてサポートされています。)そのため、JISエンコードすると文字化けして「?」が返ってきます。iso-2022-jpでは変換できない文字はすべて「?」で変換されるため、「?」は第三水準、第四水準の文字もしくはJISがサポートしていないアラビア文字などと言えます。もともと「?」の場合もあるのでJISエンコーディング前の文字が「?」の場合を除きます。


第三水準および第四水準の文字をエラーとするコードは以下のようになります。

  if (byteData.Length == 1) 
  {
    // 1バイトコード
    if ((byteData[0] >= 32) && (byteData[0] <= 126))
    {
      isError = true;
    } else if (((byteData[0] == 63)) && (testChar != @"?"))
    {
       // 63 = ?. エンコーディング前の文字が ? ではない場合はエラー
       isError = true;
    }
  }


第三水準か第四水準かを判定する場合はUnicodeで判定する必要があり、その場合は区点では判定できません。そのため文字ごとにUnicodeで判定する必要があると考えられます。


新しいISO-2022-JP-2004エンコーディングがサポートされるようになれば面区点による判定ができるようになります。(JIS X 0213 からは区点に加えて面の3つで判定する)