Improving multiple find / replace on HTML string

I'm trying to write some code that will be used for making HTML emails.  The problem is that the code seems to be very, very inefficient and I'd like to improve it if possible.  The code below reads a HTML file into a string then runs a number of string.replace() functions to get the correct output.  This is a very stripped down version of what I have:

      Dim sr As System.IO.StreamReader = New System.IO.StreamReader("htmlfile.htm")
      Dim s As String = sr.ReadToEnd

      s = s.Replace("##Date##", "Date value")
      s = s.Replace("##ADDRESS##", "Address value")

Below is an example of the HTML in the file (Sorry, I know this bit is a little obvious)

In my code I'm running s = s.replace() more than 10 times, and given this reads the entire string, modifies it and then writes it again I'm thinking it can't be the best way of doing it.  Can anyone think of any way that I can do all of the replacements in one go or improve the code in any way?

Thanks in advance.
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Using a StringBuilder would most likely improve performance.

using System.Text;

StringBuilder sb = new StringBuilder("initial value");
sb.Replace("1", "a");
sb.Replace("2", "b");
You could also do something like this:

using System.Text;

string[] oldVal = new string[]{"##DATE##", "##ADDRESS##"};
string[] newVal = new string[]{DateTime.Now.ToString(), "123 Main Street"};

StringBuilder sb = new StringBuilder(htmlString);
for(int i = 0; i < oldVal.Length; i++)
      sb.Replace(oldVal[i], newVal[i]);

Response.Write("The new HTML " + sb.ToString());

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
PsychotextAuthor Commented:
Thanks for that.  I'll run some tests to see how it works out performance wise.
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

That seems to be a hardway of reading text for e-mail. Why dont you just hard code the text and get rid of the difficulty. If you want this to be more complicated :p, you can embed your string in resource file and then read from there:

Its not a complete code. Just an idea on how you can make it easier if you do not change your e-mail text very often:

StringBuilder sb = new StringBuilder();
sb.Append("Dear "+strUserName+"\r\n");
sb.Append("Some more text \r\n");
sb.Append("Thank you\r\n");

myMailMessage.Body = sb.ToString();

HTH, Nauman.
Hi Psychotext,

you can inprove the performance if you use Regular expressions, like

s = Regex.Replace(s, "##DATE##", "Date value" )
s = Regex.Replace(s, "##ADDRESS##", "Address value")

PsychotextAuthor Commented:
nauman:  That's the way I would normally do it, but the client wants the ability to edit their own HTML files to use as a template for the HTML emails.  It'll all end in tears... ;-)
PsychotextAuthor Commented:
Ok, testing complete.  What I did is set each way of doing it up in a sub and call the sub 500 times.  Times are taken from the trace page.  For fun I included the Nauman's HTML from scratch method too.  I was a little suprised by some of the results so I gave it all a second run (Times shown in brackets):

Initial Code (Mine):
      Run 1:      1.683910 (1.783089)
      Run 2:      1.692010 (1.758817)
      Run 3:      1.682849 (1.709526)
      Run 4:      1.717491 (1.701330)
      Run 5:      1.687957 (1.690669)
      AVERAGE:      1.6928434 (1.7286862)

Regex Code (mmarinov):
      Run 1:      1.688086 (1.736237)
      Run 2:      1.689304 (1.997267)
      Run 3:      1.640872 (1.745414)
      Run 4:      1.648548 (1.732736)
      Run 5:      1.654695 (1.714441)
      AVERAGE:      1.6643010 (1.785219)

String Builder (timbo87 - Post 1):
      Run 1:      1.451863 (1.419885)
      Run 2:      1.386998 (1.396693)
      Run 3:      1.393115 (1.399178)
      Run 4:      1.385554 (1.398820)
      Run 5:      1.435610 (1.401689)
      AVERAGE:      1.4106280 (1.403253)

Old & New (timbo87 - Post 2):
      Run 1:      1.446688 (1.420638)
      Run 2:      1.385504 (1.399974)
      Run 3:      1.386387 (1.408367)
      Run 4:      1.386811 (1.439679)
      Run 5:      1.394764 (1.395636)
      AVERAGE:      1.4000308 (1.4128588)

HTML From Scratch (Nauman_ahmed):
      Run 1:      0.171699 (0.171120)
      Run 2:      0.122329 (0.122359)
      Run 3:      0.123531 (0.124216)
      Run 4:      0.125959 (0.126573)
      Run 5:      0.123910 (0.123147)
      AVERAGE:      0.1334856 (0.133483)

Not a lot to call between Timbo's methods.  They both shave some time off the prodedure.   Looks like the main bottleneck (Unsurprisingly) is actually getting the file off the disk for reading.  This is fairly well demonstrated by Nauman's method and the fact it's over 10x faster than the others.

I think I may cache the file in memory until it changes on the disk; should speed things up a fair bit.
Experts, what do you think if Psychotext creates a user control, add the HTML, and where it is needed to put the dynamically generated data, create server controls e.g. Label etc. The HTML can be grabbed from the user control easily. In the past, Aeros posted some code to get the HTML but I couldnt find that link. Will this way be little easier?

Best, nauman.
Got the link:


Table innerTable = new Table();
  Table mainTable = new Table();
  mainTable.Rows.Add(new TableRow());
  mainTable.Rows.Add(new TableRow());
  mainTable.Rows[0].Cells.Add( new TableCell());

  System.IO.StringWriter sw = new System.IO.StringWriter();
  HtmlTextWriter htmltw = new HtmlTextWriter(sw);
  String strHTML = sw.ToString();

Any ideas on how we can grab the HTML from the user control?

PsychotextAuthor Commented:
To be fair I've split the points awarded for this post as everyone helped toward the answer.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.