Top / プログラミングテクニック / 05.バイト型配列

文字とバイト型配列

文字列型を、以下のように、バイト型配列に変換することができます。

   Dim strSource As String
   Dim abytArray() As Byte
   strSource = "文字だよ"
   abytArray() = strSource

また逆に、バイト型配列を、文字列型に変換することも出来ます。

   strSource = abytArray()

何の役に立つか?2つほど例を挙げておきます。

API で Unicode を使う

通常、Byval xxx As String と宣言した場合、VBの内部では、Unicode を、Ansi に変換して、API に渡し、API から受け取った文字列は、Ansi から、Unicode に変換されます。

しかし、一部の API では、Unicode 文字列を渡したり、受け取ったりする必要がありますが、Byval xxx As String は、上に書いた理由で使えません。

こういう時は、バイト型配列を使います。

Private Declare Function Hoge Lib "Fool.DLL" (bytArray As Byte) As Long

ここで、bytArray には、Unicode を渡す必要があるものとすると、

   Dim abytArray() As Byte
   Dim lngRet As Long
   abytArray() = "Unicode だよーん"
   lngRet = Hoge(abytArray(0))

とすることで、Unicode を渡せます。

逆に、受け取るときは、

   Dim abytArray(256) As Byte
   Dim strDest As String
   Dim lngRet As Long
   lngRet = Hoge(abytArray(0))
   strDest = abytArray()

とすると、めでたく、Unicode のまま、受け取ることが出来ます。

固定長テキストファイルを使う

文字列が格納された、固定長のテキストファイルは、文字列で読み込むと、Unicode へ変換される過程で、半角が2バイトになってしまうので、読み込んだ結果が不定長になってしまいます。

このような時も、バイト型配列を使うと、非常に便利です。

1レコードが次のような、固定長のテキストファイルがあるものとします。

コード名前改行コード
4バイト20バイト2バイト

これを、構造体で、次のように表わします。

Private Type typRecord
   bytCode(1 To 4) As Byte
   bytName(1 To 20) As Byte
   bytCRLF(1 To 2) As Byte
End Type

この構造体を使って、固定長テキストファイルを読み込むコードは、次のようになります。

   Dim lngFNO As Long
   Dim udtRec As typRecord
   Dim lngPos As Long
   Dim strCode As String
   Dim strName As String
   lngFNO = FreeFile()
   Open "HOGE" For Random As #lngFNO Len = Len(udtRec)
   For lngPos = 1 To LOF(lngFNO) \ Len(udtRec)
       Get #lngFNO, lngPos, udtRec
       With udtRec
           strCode = StrConv(.bytCode, vbUnicode)           ' この部分がミソです。
           strName = StrConv(.bytName, vbUnicode)
       End With
   Next
   Close #lngFNO
 

StrConv 関数を使って、Ansi で格納された文字を、Unicode に変換します。

逆に書き込むときは、ちょっと厄介です。

   With udtRec
       .bytCode = StrConv("001", vbFromUnicode)
   End With

とやると、「配列には割り当てられません」と、コンパイルエラーが出てしまいます。

こういう場合は、いったん、動的配列に格納して、それをコピーします。そこで、LSetByteArray というサブルーチンを作ります。

Sub LSetByteArray(abytArray() As Byte, strDest As String)
   Dim bytArray() As Byte
   Dim i As Long
   Dim ai As Long
   bytArray() = StrConv(strDest, vbFromUnicode)
   i = LBound(bytArray)
   ai = LBound(abytArray) 
   Do
       If i > UBound(bytArray) Then Exit Do
       If ai > UBound(abytArray) Then Exit Do
       abytArray(ai) = bytArray(i)
       i = i + 1
       ai = ai + 1
   Loop
  ’ 余った部分にスペースを埋めます
   Do Until ai > UBound(abytArray)
       abytArray(ai) = AscB(Space(1))
       ai = ai + 1
   Loop
End Sub

使うときは、

   With udtRec
       LSetByteArray .bytCode(), strCode
       LSetByteArray .bytName(), strName
       LSetByteArray .bytCRLF(), vbCrLf
   End With

とします。

RtlMoveMemory API を使用して、コピーする方法もあるのですが、VB で出来ることを、あえて API を使う必要もないなと考え、このようにしました。

1フィールドに半角、全角のどちらかしか入らない。といった場合にはバイト型で宣言する必要はありません。

Private Type typRecord
   strCode As String * 4
   strName AS String * 20
   strCRLF As String * 2
End Type

と宣言しておけば、代入も楽チンです。




トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   最終更新のRSS
Last-modified: 2009-10-25 (日) 23:55:57 (2920d)