3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Visual BasicAdvent Calendar 2019

Day 16

【今さら極める VB6 -Part 1】文字列連結の100倍高速化(VB6 版 StringBuilder)

Last updated at Posted at 2019-12-15

ADODB.Stream クラスの WriteText メソッドを使用することにより、文字列の連結を高速に行うことができます。

手法と技術的背景

文字列連携のパフォーマンス

String はイミュータブル(不変)であり、生成後に値を変更できないため、文字列を連結する際は新たにインスタンスを生成することになります。
String の連結を繰り返すとメモリを消費し、処理速度が大きく低下するため、.NET では変更可能な文字列クラス StringBuilder の使用が推奨されています。
VB6 にはこれに相当するクラスが用意されていませんので、自前で作りました。

ADO によるストリームアクセス

ADO(Microsoft ActiveX Data Objects)は、古くは MDAC(Microsoft Data Access Components)、Vista 以降は Windows DAC(Windows Data Access Components)の一部として、Windows OS に含まれています。
VB6 でデータベースにアクセスする際の標準的なライブラリとして広く使用されていますが、「ADO の基礎」に列挙されているように、データベース以外の「データソース」も扱うことができるように設計、実装されています。
ADODB.Stream クラスは、一般的にはファイルアクセスに使用することが多いと思いますが、メモリ内で使用することもできます。

改善例

ケース

20文字 × 10,000行 を行ごとに連結

処理時間

40秒 → 0.4秒(100倍高速化)

使用イメージ

下記 StringBuilder クラスを使って、
sLines = sLines & "Line" & vbCrLf
に相当する処理を
sb.AppendLine("Line")
のように記述し、ToString() で連結後の文字列を取得することができます。

変数宣言する場合
Dim sb As StringBuilder
Set sb = New StringBuilder
Call sb.Append("変数")
Call sb.AppendLine("を使います")
Debug.Print sb.ToString()
Withブロックで使用する場合
With New StringBuilder
    Call .Append("With ブロック")
    Call .AppendLine("を使います")
    Debug.Print .ToString()
End With

VB6 版 StringBuilder クラスのソースコード

StringBuilder.cls
Option Explicit

'改行文字
Public Enum LineSeparatorsEnum
    adCR = 13
    adCRLF = -1
    adLF = 10
End Enum

'ストリームオブジェクト
Private mStream As Object 'ADODB.Stream

'改行文字 ※既定は CR+LF
Public Property Get LineSeparator() As LineSeparatorsEnum
    LineSeparator = mStream.LineSeparator
End Property
Public Property Let LineSeparator(ByVal e As LineSeparatorsEnum)
    mStream.LineSeparator = e
End Property
 
'文字列の長さ
Public Property Get Length() As Long
    If mStream.Size <= 0 Then
        Length = mStream.Size
    Else
        'Len(ToString()) だと遅い。
        'UTF-16 なので1文字2バイトと換算。Len 関数同様、サロゲートペアには対応していない。
        Length = (mStream.Size / 2) - Len(vbNullChar)
    End If
End Property

'コンストラクタ
Private Sub Class_Initialize()
     
    Set mStream = CreateObject("ADODB.Stream")
    mStream.Type = 2 'adTypeText
    LineSeparator = adCRLF
    'Charset は既定の "Unicode"(UTF-16)
    
    Call mStream.Open
     
End Sub

'文字列を追加する。
Public Function Append(ByVal s As String) As StringBuilder
     
    Call mStream.WriteText(s, 0) 'adWriteChar
    
    Set Append = Me
     
End Function

'改行付で文字列を追加する。
Public Function AppendLine(Optional ByVal s As String = "") As StringBuilder
     
    Call mStream.WriteText(s, 1) 'adWriteLine
    
    Set AppendLine = Me
     
End Function

'文字列化する。
Public Function ToString() As String
     
    mStream.Position = 0
    ToString = mStream.ReadText()
    mStream.Position = mStream.Size
     
End Function

'デストラクタ
Private Sub Class_Terminate()
     
    Call mStream.Close
     
End Sub

これで終わりません。
翌日公開の Part 2 に続きます。

3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?