Efficient String Manipulations with StringBuilder
by Budi Kurniawan07/15/2002
The System.String class is one of the most commonly used classes in .NET
programming. It is immutable, however; once set, the content of a String object cannot be modified. Trying to change its value succeeds, but this actually destroys the old String object and creates a new one.
String manipulation is not taboo though -- if you know the right class to use.
Prior to .NET, VB programmers were used to the String data type. It was easy to use, flexible, and often inevitable. Besides, there was no choice. When they upgraded to VB.NET, they found the same String data type wrapping the .NET Framework
System.String class. It is still as easy to use, as flexible, and as important as the old String data type. However, there is now an alternative if you need to manipulate strings and
avoid resource-hungry and time-consuming object creation. The alternative is
somewhat hidden in the System.Text namespace: the StringBuilder class.
Constructing A StringBuilder Object
The System.Text.StringBuilder class is faster because it allocates an initial space when
an instance of it is created. By default, a StringBuilder object created using the
StringBuilder class' no-argument constructor reserves a space for 16 characters in
memory. Therefore, if you later append more characters to it, as long as there is room for
the new characters, no new StringBuilder needs to be created. The initial space depends
on the implementation. This could be different in non-Windows implementation of the .NET Framework.
|
Related Reading VB.NET Core Classes in a Nutshell |
The size of a StringBuilder object's storage can be obtained from the class' Capacity property. For example, the following code instantiates a StringBuilder object using the no-argument constructor and writes the capacity to the Console.
Dim sb As New System.Text.StringBuilder()
System.Console.WriteLine(sb.Capacity) ' prints 16
You can change the capacity by assigning a different value to the Capacity property.
The same capacity is also set aside if you construct an instance by passing a String
object, such as the following.
Dim sb As New System.Text.StringBuilder("Brainy")
System.Console.WriteLine(sb.Capacity) ' prints 16
However, if the string passed to the constructor exceeds 16 characters, the
StringBuilder object will allocate enough space to accommodate all of the characters in
the string. In this case, the initial capacity will be double the lower capacity. For example, the following code constructs a StringBuilder object by passing a string
consisting of 20 characters. To accommodate the whole string, an initial capacity of 32 is
allocated.
Dim sb As New System.Text.StringBuilder(
"12345678901234567890")
System.Console.WriteLine(sb.Capacity) ' prints 32
The next initial capacity, supposing you pass a string of 33 characters, will be 64 (2 x
32) and not 48 (3 x 16).
The length of the string in a StringBuilder object can be obtained from its Length
property. As an example, the following code prints both the capacity and the string
length.
Dim sb As New System.Text.StringBuilder(
"12345678901234567890")
System.Console.WriteLine(sb.Capacity) ' prints 32
System.Console.WriteLine(sb.Length) ' prints 20
The capacity must be equal to or greater than the length. If you change the Capacity
property value to a number less than the length of the internal string, a
System.ArgumentOutOfRangeException will be thrown.
However, if you append a string to a StringBuilder object and the operation results in
a string whose length exceeds the StringBuilder object's capacity, the capacity will be
increased automatically. Be warned, though: the key to getting the most benefit from the StringBuilder class is to make sure that the length of the string it contains is always
less than the capacity. In other words, the performance will degrade if a StringBuilder
object has to allocate more memory to increase its capacity.
To ensure you can assign a big enough initial capacity, the StringBuilder class
provides another constructor that accepts an integer. This integer will be the initial
capacity for the StringBuilder object.
Public Sub New (ByVal capacity As Integer)
If you want to instantiate a StringBuilder object by passing a String, but want to define
your own initial capacity, use the constructor that accepts a String and an integer.
Public Sub New (ByVal value As String,
ByVal capacity As Integer)
The StringBuilder class also allows you to specify the maximum capacity that an
instance can grow to, using the following constructor.
Public Sub New (ByVal capacity As Integer,
ByVal maxCapacity As Integer)
The maximum capacity can be obtained from the MaxCapacity property. If you
construct a StringBuilder object without specifying a maximum capacity, the default will
be the same as Int32.MaxValue. Like the Capacity property, the default value of
MaxCapacity is implementation-dependent.
Now, let's have a look at other features that come with the StringBuilder class.
Accessing Individual Characters
Like the System.String class, the StringBuilder class allows you to access each individual
character of its internal string by using the Chars property.
For example, the following code constructs a StringBuilder object by passing the
string "brainy," and then prints the first character of the string.
Dim sb As New System.Text.StringBuilder("brainy")
System.Console.WriteLine(sb.Chars(0)) ' prints b
The Chars property of the StringBuilder class is more flexible than the same property
in the String class, because in StringBuilder the Chars property is read-write, whereas the
String class' Chars property is read-only. This makes StringBuilder objects very flexible, because you can also write to individual characters. Consider the following example.
Dim sb As New System.Text.StringBuilder("dingdong")
sb.Chars(0) = "p"c
sb.Chars(4) = "p"c
System.Console.WriteLine(sb) ' prints pingpong
sb.Chars(0) = "k"c
sb.Chars(4) = "k"c
System.Console.WriteLine(sb) ' prints kingpong
Appending A Value
You use the Append method to append a value to the existing string. This method has 19
overloads to make sure you can append values in any format. Therefore, you can append
a string, a byte, an integer, a long, an Object, a Single, a Double, and array of characters,
and so on. For example, the following snippet appends a string and an integer to a
StringBuilder object.
Dim sb As New System.Text.StringBuilder()
Dim text As String = "Total product(s): "
Dim count As Integer = 19
sb.Append(text).Append(count)
System.Console.WriteLine(sb)
' prints Total product(s): 19
Inserting A Value
To insert a new value to an existing StringBuilder object, you use the Insert method. This
method has 18 overloads that accept a value of any format. Each overload accepts two or
more arguments, the first being the index indicating the insertion point. For example,
here is the signature of the Insert method overload with which you can append an integer.
Overloads Public Function Insert( _
ByVal index As Integer, _
ByVal value As Integer) _
As StringBuilder
Note that the Insert method returns a StringBuilder object that is the reference to the same instance.
For example, the following code constructs a StringBuilder object with an initial
string value and then inserts a new string at index 0.
Dim sb As New System.Text.StringBuilder("
product(s): 19")
sb.Insert(0, "Total ")
System.Console.WriteLine(sb)
' prints Total product(s): 19
Removing A Substring
You can remove a range of characters from a StringBuilder object using the Remove
method. The signature of this method is as follows.
Public Function Remove( _
ByVal startIndex As Integer, _
ByVal length As Integer)
As StringBuilder
Where startIndex is the start index at which the removal begins, and length is the number of characters to be removed. For example, the following code removes the "or"
from "War and or Peace."
Dim sb As New System.Text.StringBuilder("
War and or Peace")
sb.Remove(8, 3)
System.Console.WriteLine(sb)
' prints War and Peace
Replacing Characters and Substrings
You can replace an individual character in a StringBuilder object with another character
or a substring with another substring using the Replace method. In particular, you use one
of the following overloads.
Overloads Public Function Replace( _
ByVal oldChar As Char, _
ByVal newChar As Char ) _
As StringBuilder
Overloads Public Function Replace( _
ByVal oldValue As String, _
ByVal newValue As String ) _
As StringBuilder
For example, in the following code you replace all occurrences of "d" with "k."
Dim sb As New System.Text.StringBuilder("dingdong")
sb.Replace("d"c, "k"c)
System.Console.WriteLine(sb) ' prints kingkong
As another example, the following replaces the word "and" with "or."
Dim sb As New System.Text.StringBuilder("table and
chair and wheelchair")
sb.Replace("and", "or")
System.Console.WriteLine(sb) ' prints table or
chair or wheelchair
The other two overloads of the Replace method enable you to specify a range of
positions of characters to be replaced. The signatures are as follows.
Overloads Public Function Replace( _
ByVal oldChar As Char, _
ByVal newChar As Char, _
ByVal startIndex As Integer, _
ByVal count As Integer ) _
As StringBuilder
Overloads Public Function Replace( _
ByVal oldValue As String, _
ByVal newValue As String, _
ByVal startIndex As Integer, _
ByVal count As Integer ) _
As StringBuilder
For example, the following code replaces the first "d" in "dingdong" but not the second "d."
Dim sb As New System.Text.StringBuilder("dingdong")
sb.Replace("d"c, "k"c, 0, 2)
System.Console.WriteLine(sb) ' prints kingdong
As another example, the following example replaces the first "and" but not the second one.
Dim sb As New System.Text.StringBuilder("table and
chair and wheelchair")
sb.Replace("and", "or", 0, 10)
System.Console.WriteLine(sb) ' prints table or
chair and wheelchair
Converting Into String
A multiplicity of methods in various .NET classes expect a String object as an argument.
Therefore, it is important to convert a StringBuilder object into a String object before you pass it to one of those methods. The StringBuilder class provides you with the ToString method. Using this method is very simple. For instance, here is the code that converts a StringBuilder object into a String.
Dim sb As New System.Text.StringBuilder("Total
product(s): 19")
System.Console.WriteLine(sb.ToString())
' prints Total product(s): 19
Budi Kurniawan is a senior J2EE architect and author.
Return to .NET DevCenter


