VB.NET バイト単位の文字列処理 LeftB MidB RightB

VB.NETの文字列はユニコードUTF-16(2バイト)が使用されます。

半角文字も全角文字も2バイトで表現されるので、
“ストリング” と言う文字列が10バイトと言うのは分かりますが、
“aaaaa” と言う半角文字列も10バイト使用されるのです。

しかし、業務上の理由などで、
文字列をバイト単位で処理したい場合があると思いますので、
その方法について説明していきたいと思います。

文字列をバイト単位で処理してくれる関数は
VB.NETには無いようなので、自作する事になります。
(VB6.0ではLeftB, MidB, RightB関数があったようです。)

その関数を疑似的にVB.NETで作ってみます。

まず、文字列をバイト単位で扱いたいときは、
文字コードをユニコードからShift-JISへ変換します。

そうすると、
半角文字が1バイト、全角文字が2バイトの混合文字列に変換されます。

その状態でバイト単位の文字列処理を行います。

サンプルを作ってみましたので、
アレンジして使ってください。

    Sub Main()
        Dim str As String = "文字列aaa終端"

        '左端から??バイトを取得
        '"文字列aaa終端"
        Console.WriteLine(myLeftB(str, 1)) 'エラー
        Console.WriteLine(myLeftB(str, 2)) '文
        Console.WriteLine(myLeftB(str, 3)) 'エラー
        Console.WriteLine(myLeftB(str, 4)) '文字
        Console.WriteLine(myLeftB(str, 7)) '文字列a
        Console.WriteLine(myLeftB(str, 10)) 'エラー
        Console.WriteLine(myLeftB(str, 11)) '文字列aaa終
        Console.WriteLine()

        '中間文字列を取得
        '"文字列aaa終端"
        Console.WriteLine(myMidB(str, 1, 2)) '文
        Console.WriteLine(myMidB(str, 1, 3)) 'エラー
        Console.WriteLine(myMidB(str, 1, 4)) '文字
        Console.WriteLine(myMidB(str, 2, 3)) 'エラー
        Console.WriteLine(myMidB(str, 7, 3)) 'aaa
        Console.WriteLine(myMidB(str, 7, 4)) 'エラー
        Console.WriteLine(myMidB(str, 10, 4)) '終端
        Console.WriteLine(myMidB(str, 11, 3)) 'エラー
        Console.WriteLine()
        Console.WriteLine(myMidB(str, 3)) '字列aaa終端
        Console.WriteLine(myMidB(str, 2)) 'エラー
        Console.WriteLine(myMidB(str, 7)) 'aaa終端
        Console.WriteLine()

        '右端から??バイトを取得
        '"文字列aaa終端"
        Console.WriteLine(myRightB(str, 4)) '終端
        Console.WriteLine(myRightB(str, 3)) 'エラー
        Console.WriteLine(myRightB(str, 7)) 'aaa終端
        Console.WriteLine(myRightB(str, 8)) 'エラー

    End Sub

    Function myLeftB(ByVal str As String, blen As Integer) As String
        Dim Enc As System.Text.Encoding = System.Text.Encoding.GetEncoding("Shift_JIS")
        Dim bStr As Byte() = Enc.GetBytes(str)

        'マルチバイト情報を取得
        Dim dic As New Dictionary(Of Integer, Integer)()
        dic = makeDicMultibyteStringInfo(bStr)

        '指定された数値のエラーチェック
        '終わりのバイト位置が「マルチバイトの1バイト目」だったらエラー
        If dic(blen) = 1 Then
            Return "エラー"
        Else
            Return Enc.GetString(bStr, 0, blen)
        End If

    End Function

    Function myMidB(ByVal str As String, iStart As Integer) As String
        Dim Enc As System.Text.Encoding = System.Text.Encoding.GetEncoding("Shift_JIS")
        Dim bStr As Byte() = Enc.GetBytes(str)

        'マルチバイト情報を取得
        Dim dic As New Dictionary(Of Integer, Integer)()
        dic = makeDicMultibyteStringInfo(bStr)

        '指定された数値のエラーチェック
        '始まりのバイト位置が「マルチバイトの2バイト目」だったらエラー
        If dic(iStart) = 2 Then
            Return "エラー"
        End If
        Return Enc.GetString(bStr, iStart - 1, bStr.Length - iStart + 1)
    End Function

    Function myMidB(ByVal str As String, iStart As Integer, blen As Integer) As String
        Dim Enc As System.Text.Encoding = System.Text.Encoding.GetEncoding("Shift_JIS")
        Dim bStr As Byte() = Enc.GetBytes(str)

        'マルチバイト情報を取得
        Dim dic As New Dictionary(Of Integer, Integer)()
        dic = makeDicMultibyteStringInfo(bStr)

        '指定された数値のエラーチェック
        '始まりのバイト位置が「マルチバイトの2バイト目」だったらエラー
        If dic(iStart) = 2 Then
            Return "エラー"
        End If

        '終わりのバイト位置が「マルチバイトの1バイト目」だったらエラー
        If dic(iStart + blen - 1) = 1 Then
            Return "エラー"
        End If
        Return Enc.GetString(bStr, iStart - 1, blen)
    End Function

    Function myRightB(ByVal str As String, blen As Integer) As String
        Dim Enc As System.Text.Encoding = System.Text.Encoding.GetEncoding("Shift_JIS")
        Dim bStr As Byte() = Enc.GetBytes(str)

        'マルチバイト情報を取得
        Dim dic As New Dictionary(Of Integer, Integer)()
        dic = makeDicMultibyteStringInfo(bStr)

        '文字列aaa終端

        '指定された数値のエラーチェック
        '始まりのバイト位置が「マルチバイトの2バイト目」だったらエラー
        If dic(bStr.Length - blen + 1) = 2 Then
            Return "エラー"
        End If

        Return Enc.GetString(bStr, (bStr.Length - blen), blen)
    End Function

    Function makeDicMultibyteStringInfo(ByRef bStr As Byte()) As Object

        Dim dic As New Dictionary(Of Integer, Integer)()
        '全角文字の存在する場所(何バイト目か)を調べる
        '1バイト目か、2バイト目かの情報を得ておく
        Dim i As Integer = 0
        While i < bStr.Length
            If SJIS1stbyteCheck(bStr.GetValue(i)) = True Then
                dic.Add(i + 1, 1) '全角1バイト目だったら1
                dic.Add(i + 2, 2) '全角2バイト目だったら2
                i = i + 2
            Else
                dic.Add(i + 1, 3) '半角だったら3
                i = i + 1

            End If
        End While
        Return dic
    End Function

    Function SJIS1stbyteCheck(ByVal b As Byte) As Boolean
        If ((b >= &H81) AndAlso (b <= &H9F)) OrElse ((b >= &HE0) AndAlso (b <= &HFC)) Then
            Return True
        Else
            Return False
        End If
    End Function