Help us understand the problem. What is going on with this article?

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

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 に続きます。

CodeOne
【品質と生産性にこだわるシステム開発】 .NET(C#/VB.NET)専門・リモート開発歴10年。即日・1時間から頼める常駐しないエンジニア。確かな技術で開発チームを手堅くサポートします。
https://codeone.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした