いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

.NET クラスライブラリ探訪-025 (System.Globalization.StringInfo)(サロゲートペア, LengthInTextElements)


今回は、System.Globalization.StringInfoクラスです。
System.Globalization名前空間自体、あまり馴染みがない名前ですが
このクラスは、サロゲートペアの文字列を処理する際に役に立ちます。


サロゲートペアとは何ぞや?という場合は


が詳細に記述されていますので、ご参照下さい。
今は、普段あまり見かけない文字で、且つ、1文字が2バイト以上となる
文字と認識しておいて下さい。


.NET Frameworkは内部ではUTF-16で文字列を符号化しています。
なので、たまに1文字が2バイトでない文字に出くわす事があります。


有名なのが、魚のホッケという文字です。
(漢字は、魚へんに花と書きます。)


この文字はサロゲートペアとなっていまして
1文字が4バイトとなっています。


この文字を通常のSystem.StringクラスのLengthプロパティで
確認すると、2と返ってきます。


でも、実際には漢字1文字です。
同じ魚の漢字の、鮪はちゃんとLengthプロパティが1と返ってきます。


こんな時に2文字ではなくちゃんと1文字として認識させる際に
StringInfoクラスを利用します。


以下のようにして利用します。

string testStirngs = "\uD867\uDE3D"; // ホッケの文字コード

StringInfo si = new StringInfo(testStrings);

// 文字列を取得
si.String;
// 長さを取得
si.LengthInTextElements;


上記のLengthInTextElemetsプロパティを利用します。
先のホッケの文字でも、LengthInTextElemetsプロパティを
利用するとちゃんと、1と返ってきます。


以下、サンプルです。

#region StringInfoSamples-001
    public class StringInfoSamples001 : IExecutable
    {
        public class StringInfoSampleForm : Form
        {
            public StringInfoSampleForm()
            {
                InitializeComponent();
            }

            void InitializeComponent()
            {
                SuspendLayout();

                Size = new Size(350, 100);
                StartPosition = FormStartPosition.CenterScreen;
                Text = "サロゲートペアの確認サンプル";


                TextBox t = new TextBox();
                t.Text = "\uD867\uDE3D"; // 魚へんに花という文字。魚のホッケの文字を指定。

                Button b = new Button{ Text="Exec" };
                b.Click += (s, e) => 
                {

                    string str = t.Text;
                    MessageBox.Show(string.Format("文字:{0}, 長さ:{1}", str, str.Length), "Stringでの表示");

                    //
                    // サロゲートペアの文字列
                    //
                    // サロゲートペアの文字列は1文字で
                    // 4バイトなどとなる。
                    //
                    // サロゲートペアの文字列に対して
                    // String.Lengthプロパティで長さを取得すると
                    // 1文字なのに2と返ってくる。
                    //
                    // これを1文字として認識するには以下のクラスを利用する。
                    //
                    // System.Globalization.StringInfo
                    //
                    // このクラスの以下のプロパティを利用することで
                    // 1文字と認識することが出来る。
                    //
                    // LengthInTextElementsプロパティ
                    //
                    StringInfo si = new StringInfo(str);
                    MessageBox.Show(string.Format("文字:{0}, 長さ:{1}", si.String, si.LengthInTextElements), "StringInfoでの表示");
                };

                FlowLayoutPanel contentPane = new FlowLayoutPanel{ FlowDirection=FlowDirection.TopDown, WrapContents=true };
                contentPane.Controls.AddRange(new Control[]{ t, b });
                contentPane.Dock = DockStyle.Fill;

                Controls.Add(contentPane);

                ResumeLayout();
            }
        }

        public void Execute()
        {
            
            Application.EnableVisualStyles();
            Application.Run(new StringInfoSampleForm());
        }
    }
#endregion


StringInfoクラスには、他にも
指定されたインデックスにあるテキスト要素を取り出すGetNextTextElementメソッドや
substringを行うSubstringByTextElementメソッドが存在しますが
ここでは割愛します。


================================
過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。