20

Possible Duplicate:
What's the best string concatenation method using C#?

Hi,

I have a code snippet like this where a large content of data is read from a file and check each position for some value and concat a string.

This string concatenation takes large amounts of time and processing power. Is there an approach where I can reduce the execution time?

Important: Reading Content file syntax is incorrect just need to give a idea

string x;

while (var < File.Length)
{
  if (File.Content[var] == "A")
  {
       x += 1;    
  }
  else
  {
     x += 0;
  }
  var++;
}
Community
  • 1
  • 1
Sudantha
  • 15,684
  • 43
  • 105
  • 161
  • 2
    http://stackoverflow.com/questions/21078/whats-the-best-string-concatenation-method-using-c – Rob P. May 29 '11 at 04:55
  • 11
    -1: In the future, providing an example of code that is closer to what you are actually doing (and is actually C#) will help answerers write better solutions than the over-general consensus of 'use `StringBuilder`'. E.g., how you are actually reading the file, whether you're really checking each character, whether the strings you're concatenating are really single characters, etc. – Joel B Fant May 29 '11 at 05:37

6 Answers6

29

Use StringBuilder instead of string concatenations.

A StringBuilder object maintains a buffer to accommodate the concatenation of new data. New data is appended to the end of the buffer if room is available; otherwise, a new, larger buffer is allocated, data from the original buffer is copied to the new buffer, then the new data is appended to the new buffer.

String on the contrary is immutable, every time you concatenate it creates a new object and throws away old ones, which is very inefficient.

Also, you might want to set high capacity for StringBuilder in advance, if you know that the result is going to be huge. This will reduce the number of buffer re-allocations.

Taking your pseudo-code it would look like this:

StringBulder x = new StringBuilder(10000); // adjust capacity to your needs

while (var < File.Length)
{
   if(File.Content[var] == "A")
      x.Append("1"); // or AppendLine, or AppendFormat
   else
      x.Append("2");
}
Yousha Aleayoub
  • 4,532
  • 4
  • 53
  • 64
Alex Aza
  • 76,499
  • 26
  • 155
  • 134
  • actually is was the vote count ! – Sudantha May 29 '11 at 05:08
  • 4
    @Sudantha: Since it sounds as if you're new to StringBuilder, it may be worth mentioning that it is only beneficial when doing "many" concatenations. – Niklas May 29 '11 at 06:15
  • 1
    @Niklas, It is beneficial whenever you want to _change_ the string in any way (concat or deletion) and do not care about the intermin results. Even when you operate once. – Apoorv May 29 '11 at 07:43
  • @Monster Truck: I was a bit unclear. By "beneficial", I meant more performant. But please see Eric Lippert's answer here: http://stackoverflow.com/questions/3216786/concatenation-with-stringbuilder/3216821#3216821 IMHO, StringBuilder almost always hamper readability compared to String's '+' operator – Niklas May 30 '11 at 14:06
  • @Niklas, Eric and I are saying the same thing (well almost). His statement is more like a thumb-rule whereas I have attempted to generalize it. The key in my generalization is the bit about intermin results. Oh and yes, I do agree that the readability is lost and hence if it is not causing too much of a problem a simple concat will actually improve developer efficiency. I did understand beneficial correctly though --I too was referring to performance. – Apoorv May 31 '11 at 10:03
19

System.Text.StringBuilder is the type you want to use for string concatenation operations in a loop. It is going to be far more efficient. Use .Append(value) on the object during each iteration.

StringBuilder builder = new StringBuilder();

// and inside your loop 
{
    if (blah)
        builder.Append("1");
    else
        builder.Append("0");
}

string output = builder.ToString(); // use the final result
Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
7

Use a StringBuilder instead, that will perform much better - using strings you create a new string each time within the loop which causes a lot of overhead/garbage collection, using a single StringBuilder that you create outside the loop you can avoid that.

BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
7

Use StringBuilder, Strings are immutable in .net meaning that ever concatenation makes a copy of the string.

Using the StringBuilder Class (MSDN)

StringBuilder sb = new StringBuilder();
sb.Append("1") // like so
Richard
  • 106,783
  • 21
  • 203
  • 265
Matt
  • 339
  • 1
  • 5
6

Use a StringBuilder.

var sb = new StringBuilder();
sb.Append("abc");
sb.Append("def");
var str = sb.ToString();
Will
  • 2,512
  • 14
  • 19
2

When you read a file byte by byte, it can take too long. I would recommend that you read a block of bytes (for example 1024 or 2048) in the loop. Then, in the block you have read, use a regular expression to match your character, particularly if you have a extremely large file.

Sample code would be something like this:

private string GetFileData(string fileName, string matchChar)
{
    StringBuilder x = new StringBuilder();
    int blockCount = 2048;
    int offset = 0;
    string pattern = matchChar;
    int k = -1;
    using (var sr = new System.IO.FileStream(fileName, System.IO.FileMode.Open))
    {
       while ((sr.CanRead) && (k != 0))
       {
           byte[] bt = new byte[blockCount];
           k = sr.Read(bt, 0, blockCount);
           string so = System.Text.UTF8Encoding.UTF8.GetString(bt);
           var m = new System.Text.RegularExpressions.Regex(pattern).Matches(so);
           foreach (System.Text.RegularExpressions.Match item in m)
           {
               x.Append(item.Value);
           }
       }
    }
    return x.ToString();
}

You would call this as

GetFileData(@"c:\matchtest.ono", "a");
Owen Blacker
  • 4,117
  • 2
  • 33
  • 70
DeveloperX
  • 4,633
  • 17
  • 22