.NET TIPS

文字数を正確にカウントするには?(サロゲート文字対応)[C#、VB]

デジタルアドバンテージ 一色 政彦
2008/04/03

 文字列の長さを取得する場合、基本的には「TIPS:文字列の長さを取得するには?」で紹介しているように、文字列オブジェクト(=System名前空間のStringクラスのオブジェクト)のLengthプロパティを利用すればよい。

 しかし、「文字列の長さ」と「文字数」は必ずしも一致しない可能性がある。というのも、Windows Vistaの登場などにより、Unicodeのサロゲート文字が(エンド・ユーザーにより)入力される可能性が出てきているからだ。

 サロゲート文字(もしくはサロゲート・ペア文字)とは、通常「1文字=2bytes」のところが、「1文字=4bytes」となることがある文字のことだ。そのような「1文字=4bytes」のサロゲート文字の「文字列の長さ」を、先ほどのLengthプロパティを使って取得すると、「2」になる。正確な文字数は「1」なのに、文字列の長さは「2」と判定されてしまうのだ。

 そこで本稿では(サロゲート文字を考慮して)正確な文字数を取得する方法を紹介する。

文字数を取得する方法(.NET Framework 2.0以降)

 文字数を取得するには、StringInfoオブジェクト(=System.Globalization名前空間のStringInfoクラスのオブジェクト)のLengthInTextElementsプロパティを使用すればよい。StringInfoオブジェクトは、パラメータに文字列を指定してStringInfoクラスのコンストラクタを呼び出せば取得できる。

 ただし、このLengthInTextElementsプロパティは.NET Framework 2.0以降でしか利用できない。.NET Framework 1.xで文字数を取得する方法は本TIPS後半で説明する。

 次のコードは、「る」という文字列の文字数を取得するコンソール・アプリケーションのサンプル・プログラムである。

using System;
using System.Globalization;

class Program
{
  static void Main(string[] args)
  {
    // 文字列「叱る」
    string moji = "\uD842\uDF9Fる";

    // StringInfoオブジェクトの取得
    StringInfo si = new StringInfo(moji);

    // 文字列の長さ
    Console.WriteLine("文字列の長さ=" + moji.Length.ToString());

    // 文字数(サロゲート文字対応)
    Console.WriteLine("文字数=" + si.LengthInTextElements);

    // 出力結果:
    // 文字列の長さ=3
    // 文字数=2
  }
}
Imports System.Globalization

Module Module1

  Sub Main()

    ' 文字列「叱る」
    Dim moji As String = ChrW(&HD842) & ChrW(&HDF9F) & "る"

    ' StringInfoオブジェクトの取得
    Dim si As New StringInfo(moji)

    ' 文字列の長さ
    Console.WriteLine("文字列の長さ=" & moji.Length.ToString())

    ' 文字数(サロゲート文字対応)
    Console.WriteLine("文字数=" & si.LengthInTextElements)

    ' 出力結果:
    ' 文字列の長さ=3
    ' 文字数=2

  End Sub

End Module
文字数を取得するコンソール・アプリケーションのサンプル・プログラム【.NET Framework 2.0以降】(上:C#、下:VB)

文字数を取得する方法(.NET Framework 1.x以降)

 続いて.NET Framework 1.xで文字数を取得する場合だが、先ほどのコード内にあるStringInfoオブジェクトのLengthInTextElementsプロパティの呼び出しを、(本TIPSで紹介する)GetLengthInTextElementsメソッドの呼び出しに置き換えるだけだ。GetLengthInTextElementsメソッドは、パラメータに文字列を渡すと、戻り値で文字数を返す。

 次のコードは実際にGetLengthInTextElementsメソッドを使用したコンソール・アプリケーションのサンプル・プログラムである。

using System;
using System.Globalization;

class Program
{
  static void Main(string[] args)
  {
    // 文字列「叱る」
    string moji = "\uD842\uDF9Fる";

    // 文字列の長さ(char単位の数)
    Console.WriteLine("文字列の長さ=" + moji.Length.ToString());

    // 文字数(サロゲート文字対応)
    Console.WriteLine("文字数=" + GetLengthInTextElements(moji));

    // 出力結果:
    // 文字列の長さ=3
    // 文字数=2
  }

  // 文字数を取得するメソッド(.NET Framework 1.x用)
  static int GetLengthInTextElements(string textData)
  {
    int[] indexes =
      StringInfo.ParseCombiningCharacters(textData);

    return indexes.Length;
  }
}
Imports System.Globalization

Module Module1

  Sub Main()

    ' 文字列「叱る」
    Dim moji As String = ChrW(&HD842) & ChrW(&HDF9F) & "る"

    ' 文字列の長さ(Char単位の数)
    Console.WriteLine("文字列の長さ=" & moji.Length.ToString())

    ' 文字数(サロゲート文字対応)
    Console.WriteLine("文字数=" & GetLengthInTextElements(moji))

    ' 出力結果:
    ' 文字列の長さ=3
    ' 文字数=2

  End Sub

  ' 文字数を取得するメソッド(.NET Framework 1.x用)
  Function GetLengthInTextElements(ByVal moji As String) As Integer

    Dim indexes() As Integer = _
      StringInfo.ParseCombiningCharacters(moji)

    Return indexes.Length

  End Function

End Module
文字数を取得するコンソール・アプリケーションのサンプル・プログラム【.NET Framework 1.x以降】(上:C#、下:VB)

 GetLengthInTextElementsメソッドの内部では、StringInfoクラスの静的メソッドParseCombiningCharactersを呼び出している。ParseCombiningCharactersメソッドは、1文字(制御文字やサロゲート文字を含む)ごとの、(文字列中の)インデックス番号をint/Integer型の配列で返す。従って、この配列の長さ(Lengthプロパティ)を調べれば正確な文字数が判明する。

 ちなみに、文字数ではなく、文字列のバイト数を取得する方法は、「TIPS:文字列のバイト数を取得するには?」を参照してほしい。End of Article

カテゴリ:クラス・ライブラリ 処理対象:文字列
使用ライブラリ:StringInfoクラス(System.Globalization名前空間)
関連TIPS:文字列の長さを取得するには?
関連TIPS:文字列のバイト数を取得するには?

この記事と関連性の高い別の.NET TIPS
サロゲート文字かどうかを判定するには?
文字列を1文字ずつ解析するには?(サロゲート文字対応)
文字列のバイト数を取得するには?
文字列の長さを取得するには?
文字列の全角/半角をチェックするには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間