DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

文字列から指定した部分を取得する

文字列内の指定した範囲を文字列として取得するには、String.Substringメソッドを使います。Substringメソッドを使えば、Stringの指定した位置から指定した文字数分のStringを取得することができます。

以下にSubstringメソッドを使用した具体例を幾つか紹介します。文字の位置はインデックスで指定しますが、先頭の文字のインデックスが 0 なので、n 文字目のインデックスは (n-1) になることに注意してください。

VB.NET
コードを隠すコードを選択
Dim s As String = "あいうえお"

'先頭から2文字を取得する。先頭の文字のインデックスは0。
Dim s1 As String = s.Substring(0, 2)
'「あい」となる

'2文字目(インデックスは1)から3文字を取得する
Dim s2 As String = s.Substring(1, 3)
'「いうえ」となる

'4文字目(インデックスは3)から最後まで取得する
Dim s3 As String = s.Substring(3)
'「えお」となる

'文字列の長さより長い文字列を取得しようとしてみる
'Dim s4 As String = s.Substring(0, 100)
'例外ArgumentOutOfRangeExceptionが発生

'文字列の長さより大きい開始位置を指定してみる
'Dim s5 As String = s.Substring(100)
'例外ArgumentOutOfRangeExceptionが発生

'開始位置に負の数を指定してみる
'Dim s6 As String = s.Substring(-1)
'例外ArgumentOutOfRangeExceptionが発生
C#
コードを隠すコードを選択
string s = "あいうえお";

//先頭から2文字を取得する。先頭の文字のインデックスは0。
string s1 = s.Substring(0, 2);
//「あい」となる

//2文字目(インデックスは1)から3文字を取得する
string s2 = s.Substring(1, 3);
//「いうえ」となる

//4文字目(インデックスは3)から最後まで取得する
string s3 = s.Substring(3);
//「えお」となる

//文字列の長さより長い文字列を取得しようとしてみる
//string s4 = s.Substring(0, 100);
//例外ArgumentOutOfRangeExceptionが発生

//文字列の長さより大きい開始位置を指定してみる
//string s5 = s.Substring(100);
//例外ArgumentOutOfRangeExceptionが発生

//開始位置に負の数を指定してみる
//string s6 = s.Substring(-1);
//例外ArgumentOutOfRangeExceptionが発生

VB.NETでは、Mid関数を使ってSubstringメソッドと同じことができます。また、文字列の先頭から指定した長さの文字列を返すLeft関数と、文字列の末尾から指定された長さの文字列を返すRight関数もあります。これらの関数に関しては、「C#でMid、Left、Right関数の代わりになるものは?」をご覧ください。

サロゲートペアや結合文字列を含む文字列でも正しく部分文字列を取得する

Substringメソッドのパラメータに指定する開始位置や文字列の長さは、Stringオブジェクトに含まれているCharオブジェクト(StringオブジェクトのCharsプロパティが返すChar型配列)の位置と数になります。よって、2つ以上のCharオブジェクトで1つの文字を表すサロゲートペア(代用対)や結合文字列(Combining Character Sequence、組み合わせ文字シーケンス)が含まれている場合は、Unicode文字の位置と長さを指定しても思ったような結果を得られません。

補足:サロゲートペアや結合文字列については、「サロゲートペアや結合文字が含まれているか調べる」で簡単に説明しています。

サロゲートペアや結合文字列が含まれている場合でもUnicode文字数を指定して部分文字列を正しく取得するには、StringInfo.SubstringByTextElementsメソッド(System.Globalization名前空間)を使います。SubstringByTextElementsメソッドの使い方は、Substringメソッドと同じです。

VB.NET
コードを隠すコードを選択
'結合文字列を含む文字列
Dim s As String = "a" & ChrW(&H301) & "a" & ChrW(&H302) & "a" & _
    ChrW(&H303) & "a" & ChrW(&H304) & "a" & ChrW(&H305)
'StringInfoオブジェクトを作成
Dim si As New System.Globalization.StringInfo(s)

'先頭から2文字を取得する
Dim s1 As String = si.SubstringByTextElements(0, 2)

'2文字目から3文字を取得する
Dim s2 As String = si.SubstringByTextElements(1, 3)

'4文字目から最後まで取得する
Dim s3 As String = si.SubstringByTextElements(3)

'文字列の長さより長い文字列を取得しようとしてみる
'Dim s4 As String = si.SubstringByTextElements(0, 100)
'例外ArgumentOutOfRangeExceptionが発生

'文字列の長さより大きい開始位置を指定してみる
'Dim s5 As String = si.SubstringByTextElements(100)
'例外ArgumentOutOfRangeExceptionが発生

'開始位置に負の数を指定してみる
'Dim s6 As String = si.SubstringByTextElements(-1)
'例外ArgumentOutOfRangeExceptionが発生
C#
コードを隠すコードを選択
//結合文字列を含む文字列
string s = "a\u0301a\u0302a\u0303a\u0304a\u0305";
//StringInfoオブジェクトを作成
System.Globalization.StringInfo si = new System.Globalization.StringInfo(s);

//先頭から2文字を取得する
string s1 = si.SubstringByTextElements(0, 2);

//2文字目から3文字を取得する
string s2 = si.SubstringByTextElements(1, 3);

//4文字目から最後まで取得する
string s3 = si.SubstringByTextElements(3);

//文字列の長さより長い文字列を取得しようとしてみる
string s4 = si.SubstringByTextElements(0, 100);
//例外ArgumentOutOfRangeExceptionが発生

//文字列の長さより大きい開始位置を指定してみる
string s5 = si.SubstringByTextElements(100);
//例外ArgumentOutOfRangeExceptionが発生

//開始位置に負の数を指定してみる
string s6 = si.SubstringByTextElements(-1);
//例外ArgumentOutOfRangeExceptionが発生

このコードの結果、s1、s2、s3に代入される文字列は、以下のようになります(画像で表示しています)。

SubstringByTextElementsメソッドを使った例

ちなみに、SubstringByTextElementsメソッドの代わりにSubstringメソッドを使用すると、以下のような結果になります(画像で表示しています)。

Substringメソッドを使った例

SubstringByTextElementsメソッドは、.NET Framework 2.0以降でしか使用できません。以下に.NET Framework 1.1以前でも使えるStringInfo.SubstringByTextElementsメソッドの代わりになるであろうメソッドの例を示します。

VB.NET
コードを隠すコードを選択
''' <summary>
''' StringInfo.SubstringByTextElementsメソッドと同じことをする
''' </summary>
''' <param name="str">文字列</param>
''' <param name="startingTextElement">開始位置</param>
''' <param name="lengthInTextElements">長さ</param>
''' <returns>部分文字列</returns>
Public Shared Function SubstringByTextElements(ByVal str As String, _
        ByVal startingTextElement As Integer, _
        ByVal lengthInTextElements As Integer) As String
    If startingTextElement < 0 Then
        Throw New ArgumentOutOfRangeException("startingTextElement", _
                                              "正の数値が必要です。")
    End If
    If lengthInTextElements < 0 Then
        Throw New ArgumentOutOfRangeException("lengthInTextElements", _
                                              "正の数値が必要です。")
    End If

    'サロゲートペアや結合文字列を考慮したインデックスを取得する
    Dim indexes As Integer() = _
        System.Globalization.StringInfo.ParseCombiningCharacters(str)
    If str.Length = 0 OrElse indexes.Length <= startingTextElement Then
        Throw New ArgumentOutOfRangeException("startingTextElement", _
            "指定された引数は、有効な値の範囲内にありません。")
    End If
    If indexes.Length - lengthInTextElements < startingTextElement Then
        Throw New ArgumentOutOfRangeException("lengthInTextElements", _
            "指定された引数は、有効な値の範囲内にありません。")
    End If

    'Substringに指定する開始位置を取得する
    Dim start As Integer = indexes(startingTextElement)
    '最後まで取得するか
    If startingTextElement + lengthInTextElements = indexes.Length Then
        Return str.Substring(start)
    End If
    'Substringで部分文字列を取得する
    Return str.Substring(start, _
        indexes(lengthInTextElements + startingTextElement) - start)
End Function
C#
コードを隠すコードを選択
/// <summary>
/// StringInfo.SubstringByTextElementsメソッドと同じことをする
/// </summary>
/// <param name="str">文字列</param>
/// <param name="startingTextElement">開始位置</param>
/// <param name="lengthInTextElements">長さ</param>
/// <returns>部分文字列</returns>
public static string SubstringByTextElements(string str,
    int startingTextElement, int lengthInTextElements)
{
    if (startingTextElement < 0)
    {
        throw new ArgumentOutOfRangeException("startingTextElement",
            "正の数値が必要です。");
    }
    if (lengthInTextElements < 0)
    {
        throw new ArgumentOutOfRangeException("lengthInTextElements",
            "正の数値が必要です。");
    }

    //サロゲートペアや結合文字列を考慮したインデックスを取得する
    int[] indexes = System.Globalization.StringInfo.ParseCombiningCharacters(str);
    if (str.Length == 0 || indexes.Length <= startingTextElement)
    {
        throw new ArgumentOutOfRangeException("startingTextElement",
            "指定された引数は、有効な値の範囲内にありません。");
    }
    if (indexes.Length - lengthInTextElements < startingTextElement)
    {
        throw new ArgumentOutOfRangeException("lengthInTextElements",
            "指定された引数は、有効な値の範囲内にありません。");
    }

    //Substringに指定する開始位置を取得する
    int start = indexes[startingTextElement];
    //最後まで取得するか
    if (startingTextElement + lengthInTextElements == indexes.Length)
    {
        return str.Substring(start);
    }
    //Substringで部分文字列を取得する
    return str.Substring(start,
        indexes[lengthInTextElements + startingTextElement] - start);
}

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • .NET Tipsをご利用いただく際は、注意事項をお守りください。