I have downloaded a stream as a byte[] 'raw' that is about 36MB. I then convert that into a string with
string temp = System.Text.Encoding.UTF8.GetString(raw)
Then I need to replace all "\n" with "\r\n" so I tried
string temp2 = temp.Replace("\n","\r\n")
but it threw an "Out of Memory" exception. I then tried to create a new string with a StringBuilder:
string temp2 = new StringBuilder(temp).Replace("\n","\r\n").toString()
and it didn't throw the exception. Why would there be a memory issue in the first place (I'm only dealing with 36MB here), but also why does StringBuilder.Replace() work when the other doesn't?
For 50,000 iterations, the regular string concatenation takes 486 milliseconds. But the stringbuilder and char pointer code don't even show up! They are running in less than 1 millisecond. This means that the regular string concatenation is at least 486 times slower than using a stringbuilder!
Creating and initializing a new object is more expensive than appending a character to an buffer, so that is why string builder is faster, as a general rule, than string concatenation.
replace() Method. This method returns a new string resulting from replacing all occurrences of old characters in the string with new characters.
The replace() method searches a string for a value or a regular expression. The replace() method returns a new string with the value(s) replaced. The replace() method does not change the original string.
When you use:
string temp2 = temp.Replace("\n","\r\n")
for every match of "\n" in the string temp, the system creates a new string with the replacement.
With StringBuilder this doesn't happens because StringBuilder is mutable, so you can actually modify the same object without the need to create another one.
Example:
temp = "test1\ntest2\ntest3\n"
With First Method (string)
string temp2 = temp.Replace("\n","\r\n")
is equivalent to
string aux1 = "test1\r\ntest2\ntest3\n"
string aux2 = "test1\r\ntest2\r\ntest3\n"
string temp2 = "test1\r\ntest2\r\ntest3\r\n"
With Secon Method (StringBuilder)
string temp2 = new StringBuilder(temp).Replace("\n","\r\n").toString()
is equivalent to
Stringbuilder aux = "test1\ntest2\ntest3\n"
aux = "test1\r\ntest2\ntest3\n"
aux = "test1\r\ntest2\r\ntest3\n"
aux = "test1\r\ntest2\r\ntest3\r\n"
string temp2 = aux.toString()
Following StringBuilder from MSDN:
Most of the methods that modify an instance of this class return a reference to that same instance, and you can call a method or property on the reference. This can be convenient if you want to write a single statement that chains successive operations.
So when you call replace with String the new object (big data - 36MB) will be allocate to create new string. But StringBuilder accessing same instance objects and does not create new one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With