🔠

Windows 日本語カルチャ照合規則 - 漢字ソート順

2025/02/14に公開

はじめに

C#定石 - ファイル一覧 - 照合規則 で、任意にピックアップした漢字を、Windows 日本語カルチャ照合規則でソートした結果を確認しました。

文字 Unicode JIS X0213 水準 画数 部首 音読み
U+4E00 1-16-76 第1水準 1 一部 イチ・イツ
U+4E09 1-27-16 第1水準 3 一部 サン
U+4E8C 1-38-83 第1水準 2 二部
U+4E9C 1-16-1 第1水準 7 二部
U+4E9E 1-48-19 第2水準 8 二部
U+5516 1-16-2 第1水準 10 口部 ア・アク
U+555E 1-15-8 第3水準 11 口部 ア・アク
U+5561 2-4-8 第4水準 11 口部 ハイ・ヒ
U+6392 1-39-51 第1水準 11 手部 ハイ
U+67DB 2-14-50 第4水準 9 木部 シン
U+795E 1-31-32 第1水準 9 示部 シン・ジン
U+FA19 1-89-28 第3水準 10 示部 シン・ジン
var arrayItems4 = new string[] { "一", "三", "二", "亜", "亞", "唖", 
                                 "啞", "啡", "排", "柛", "神", "神" };
Array.Sort(arrayItems4);
// → "亜", "唖", "一", "三", "神", "二", "排", "亞", "神", "啞", "啡", "柛"

JIS X 0213 面区点順をベースとしているようですが、「啞」がイレギュラーという結果になったので、漢字ソート順を確認してみることにします。

参考情報

下記情報を参考にさせて頂きました。

漢字ソート順

テストデータ作成とソート実行

まず、 JIS X 0213漢字一覧 - Wikipedia から、「JIS X 0213漢字一覧の1面」「JIS X 0213漢字一覧の2面」を、Unicode タブ区切りテキストファイルに落とします。

対象ファイルの項目は「文字」「面区点」「Shift_JIS-2004」「Unicode」「水準」「備考」となっていますが、「文字」「面区点」「水準」「Unicode」「UTF16」に変更します。

// 原本 TSV → 今回利用 TSV
private void Original2Custom(string original, string custom)
{
  using (var sr = new StreamReader(original, Encoding.UTF8))
  using (var sw = new StreamWriter(custom, false, Encoding.UTF8))
  {
    // ヘッダー
    // original「文字」「面区点」「Shift_JIS-2004」「Unicode」「水準」「備考」
    // → custom「文字」「面区点」「水準」「Unicode」「UTF16」
    var line = sr.ReadLine();
    sw.WriteLine("文字\t面区点\t水準\tUnicode\tUTF16");

    // データ
    while (sr.Peek() > -1)
    {
      // 1行取得してタブ区切りで分解
      line = sr.ReadLine().Trim();
      var items = line.Split('\t');
      if (items?.Length >= 5)
      {
        sw.WriteLine(string.Format("{0}\t{1}\t{2}\t{3}\t{4}",
                              parts[0].Trim(), parts[1].Trim(),
                              parts[4].Trim(), parts[3].Trim(),
                              HexaDumpUTF16(parts[0].Trim())));
      }
    }
  }
}
// UTF16 ヘキサダンプ
private string HexaDumpUTF16(string target)
{
  var chars = target.ToCharArray();
  var sb = new StringBuilder();
  foreach (char c in chars)
  {
    sb.Append(string.Format("0x{0:X4} ", (ushort)c));
  }
  return sb.ToString().TrimEnd();
}

データ管理クラスとして CharX0213 を用意、List<CharX0213> を作成してソートします。

// 対象データ
private List<CharX0213> lstTarget = new List<CharX0213>();

// 対象ファイルロード → ソート → 結果ファイル出力
public void DoSort(string x0213_1, string x0213_2, string output)
{
  // 対象ファイルロード
  lstTarget.Clear();
  File2List(x0213_1);
  File2List(x0213_2);

  // ソート
  var sorted = lstTarget.OrderBy(x => x.Target);

  // 結果出力
  using (var sw = new StreamWriter(output, false, Encoding.UTF8))
  {
    // ヘッダ
    sw.WriteLine("文字\t面区点\t水準\tUnicode\tUTF16");
    // データ
    foreach(var item in sorted)
    {
      sw.WriteLine(string.Format("{0}\t{1}\t{2}\t{3}\t{4}",
                            item.Target, item.X0213, 
                            item.Level, item.Unicode, 
                            item.HexaDumpUTF16));
    }
  }
}
// ファイル ロード
private void File2List(string path)
{
  using (var sr = new StreamReader(path, Encoding.UTF8))
  {
    // ヘッダ
    var line = sr.ReadLine();
    // データ
    while (sr.Peek() > -1)
    {
      line = sr.ReadLine().Trim();
      var items = line.Split('\t');
      if (items?.Length >= 5)
      {
        lstTarget.Add(new CharX0213(items));
      }
    }
  }
}

public class CharX0213
{
  public string Target { get; set; }         // 文字
  public string X0213 { get; set; }          // JIS X 0213 面区点
  public string Level { get; set; }          // 第1水準, 第2水準, ...
  public string Unicode { get; set; }        // Unicode
  public string HexaDumpUTF16 { get; set; }  // UTF16 16進数

  public CharX0213(int sirial, string [] items)
  {
    if (items.Length >= 5)
    {
      Target = items[0].Trim();
      X0213 = items[1].Trim();
      Level = items[2].Trim();
      Unicode = items[3].Trim();
      HexaDumpUTF16 = items[4].Trim();
    }
  }
}

掲載ソースで作成したテストデータと、Windows 日本語カルチャ照合規則でソートした結果を GitHub にアップロードしておきました。

https://github.com/chaichai0917/SampleCode

  • Windows 日本語カルチャ照合規則 確認
    • JISX0213-1.txt(JIS X0213 漢字1面 区点順 テストデータ)
    • JISX0213-2.txt(JIS X0213 漢字2面 区点順 テストデータ)
    • JISX0213-sorted.txt(ソート結果)

結果確認

ソート結果を確認すると、末尾にサロゲートペアが固まっています。
このことから、文字クラスとして、「非サロゲートペア」<「サロゲートペア」 で分類がされているようです。

「非サロゲートペア」は、第1水準漢字と第2水準漢字については、いくつかのイレギュラー部分はありますが、JIS X 0213 面区点順をベースとしているようです。
「サロゲートペア」については、Unicode順となっています。

ソート結果全体で、JIS X 0213 面区点順ではない部分の抽出として「ひとつ前の文字の JIS X 0213 面区点よりも、該当文字の JIS X 0213 面区点が小さい」部分をピックアップすると 851ヶ所もあります。
このようなイレギュラーで、規則性を見いだせたのは、第1水準漢字の直後に、第3水準 異体字という並び順 5ヶ所のみでした。

文字 面区点 水準 Unicode UTF16
1-27-06 第1水準 U+6BBA 0x6BBA
1-86-41 第3水準 U+F970 0xF970
1-27-07 第1水準 U+85A9 0x85A9
文字 面区点 水準 Unicode UTF16
1-45-83 第1水準 U+6B04 0x6B04
1-86-27 第3水準 U+F91D 0xF91D
1-45-84 第1水準 U+6FEB 0x6FEB
文字 面区点 水準 Unicode UTF16
1-46-26 第1水準 U+865C 0x865C
1-91-47 第3水準 U+F936 0xF936
1-46-27 第1水準 U+4E86 0x4E86
文字 面区点 水準 Unicode UTF16
1-46-64 第1水準 U+985E 0x985E
1-94-04 第3水準 U+F9D0 0xF9D0
1-46-65 第1水準 U+4EE4 0x4EE4
文字 面区点 水準 Unicode UTF16
1-47-13 第1水準 U+5ECA 0x5ECA
1-84-14 第3水準 U+F928 0xF928
1-47-14 第1水準 U+5F04 0x5F04

「非サロゲートペア」部分、第2水準漢字の末尾 JIS X 0213 1-84-06 以降は、第3水準漢字、第4水準漢字となります。
1-84-06 前後(前方1文字、後方15文字)のソート順を抜粋します。

文字 面区点 水準 Unicode UTF16
1-84-05 第2水準 U+51DC 0x51DC
1-84-06 第2水準 U+7199 0x7199
1-90-23 第3水準 U+7E8A 0x7E8A
1-91-78 第3水準 U+891C 0x891C
1-93-25 第3水準 U+9348 0x9348
1-93-14 第3水準 U+9288 0x9288
2-86-53 第4水準 U+84DC 0x84DC
1-14-25 第3水準 U+4FC9 0x4FC9
2-79-64 第4水準 U+70BB 0x70BB
1-85-21 第3水準 U+6631 0x6631
1-85-73 第3水準 U+68C8 0x68C8
2-91-03 第4水準 U+92F9 0x92F9
1-85-23 第3水準 U+66FB 0x66FB
1-84-26 第3水準 U+5F45 0x5F45
1-14-04 第3水準 U+4E28 0x4E28
1-14-08 第3水準 U+4EE1 0x4EE1
2-01-31 第4水準 U+4F00 0x4F00

画数、部首、音読みは関係なさそうですよね、、、
知識不足のため、この並び順から、規則性を見出すことはできませんでした。

自然順(エクスプローラ互換)

WIN32API - StrCmpLogicalW でソートした場合についても、Windows 日本語カルチャ照合規則と同様の結果となりました。

まとめ

Windows 日本語カルチャ照合規則、および、自然順(WIN32API - StrCmpLogicalW)で漢字をソートすると下記順序となります。

  • 非サロゲートペア
    • 第1水準漢字と第2水準漢字( + 第3水準漢字 5文字)
      • 基本的に JIS X 0213 面区点順
      • 第1水準漢字の直後に、第3水準 異体字が配置されるケース有り
        • 殺(1-27-06、第1水準)殺(1-86-41、第3水準)
        • 欄(1-45-83、第1水準)欄(1-86-27、第3水準)
        • 虜(1-46-26、第1水準)虜(1-91-47、第3水準)
        • 類(1-46-64、第1水準)類(1-94-04、第3水準)
        • 廊(1-47-13、第1水準)廊(1-84-14、第3水準)
    • 第3水準漢字と第4水準漢字
      • 規則性を見出すことはできませんでした
  • サロゲートペア
    • Unicode順

出典

本記事は、2025/02/14 Qiita 投稿記事の転載です。

Windows 日本語カルチャ照合規則 - 漢字ソート順

Discussion