Helped out a guy on IRC making a method that replaces text in a file/stream, thought I’d share it. Basically it reads from one file line by line and writes to another while executing a custom replacement method on every line.
Note: This code is not optimized for speed. Although it will perform very well, it CAN be optimized a lot. This is meant as coder friendly code. However it will not use more memory when processing large files.
// Needs:
//using System;
//using System.IO;
//using System.Collections.Generic;
//using System.Text.RegularExpressions;
// By Tedd Hansen, 2010.03.12, [email protected]
// BSD-licensed, no warranties given
private void Test()
{
// First of all we need to instansiate a copy of ReplacementClass we can use
ReplacementClass myReplacementClass = new ReplacementClass();
// Build our replacement map
myReplacementClass.ReplacementMap.Clear();
myReplacementClass.ReplacementMap.Add("Color1", "#FFFFFF");
myReplacementClass.ReplacementMap.Add("Color2", "#FF00FF");
// Now do replacement
// Note that we provide a "ReplacementMethod" which will do our replacement.
myReplacementClass.ReplaceFile(@"C:\\\Temp\\\SourceFile.txt", @"C:\\\Temp\\\DestinationFile.txt", new MatchEvaluator(myReplacementClass.ReplacementMethod));
}
/// <summary>
/// Contains Replace methods for replacing $REPLACE_ID$ tokens in file or stream input+output
/// </summary>
public class ReplacementClass
{
// By Tedd Hansen, 2010.03.12, [email protected]
// BSD-licensed, no warranties given
#region ReplacementMethod(): Sample replacement method that looks up ID's in a dictionary.
/// <summary>
           /// Contains a map of ID (from $REPLACE_ID$ found in source file) to replacement text.
           /// Note that ID is case insensitive.
           /// </summary>
public Dictionary<string, string> ReplacementMap = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
/// <summary>
           /// This is where the replacement happens. Anything you return here will replace $REPLACE_*$ in the line.
           /// </summary>
public string ReplacementMethod(Match m)
{
// Get the ID part of string $REPLACE_ID$
string replacementID = m.Groups[1].Value;
// Look for this ID in our replacement dictionary
if (ReplacementMap.ContainsKey(replacementID))
return ReplacementMap[replacementID];
// Here is an example of hardcoded replacements... they may make more sense than the above.
switch (replacementID.ToLowerInvariant())
{
case "time":
return DateTime.Now.ToString("HH:mm:ss");
break;
case "date":
return DateTime.Now.ToString("yyyy-MM-dd");
break;
}
// Default: Replace it with nothing
return "";
}
#endregion
// Regex object used to quickly and easily locate text to replace
// This is where we actually define what to look for
private Regex ReplacementFinderRegex = new Regex(@"\\\$REPLACE_([^\\\$]+)\\\$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
#region ReplaceFile(): File system wrapper method for ReplaceStream()
/// <summary>
           /// Copy a file and replace content while doing so.
           /// </summary>
           /// <param name="sourceFile">Source file</param>
           /// <param name="destinationFile">Desintation file</param>
           /// <param name="replacementFunctionDelefate"></param>
public void ReplaceFile(string sourceFile, string destinationFile, MatchEvaluator replacementMethodDelegate)
{
// By using "using" we ensure that files are closed properly regardless what we forget to do or or error occurs
// Open input file so we get a FileStream object
using (FileStream inStream = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read))
{
// Open output file so we get a FileStream object
using (FileStream outStream = File.Open(destinationFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
// We use the ReplaceStream function to do the actual copying and replacement
ReplaceStream(inStream, outStream, replacementMethodDelegate);
}
}
}
#endregion
#region ReplaceStream(): Line by line stream copy with replacement
/// <summary>
           /// Read from input stream and write to output stream while modifying the content.
           /// Note: This method can be used on streams coming directly from SQL and streams going directly to webpage (Response.Stream or something)
           /// </summary>
           /// <param name="inStream">Input stream</param>
           /// <param name="outStream">Output stream</param>
public void ReplaceStream(FileStream inStream, FileStream outStream, MatchEvaluator replacementMethodDelegate)
{
using (StreamReader inStreamReader = new StreamReader(inStream))
{
using (StreamWriter outStreamWriter = new StreamWriter(outStream))
{
string inLine = null;
while ((inLine = inStreamReader.ReadLine()) != null)
{
// Send the line through our replacement method using Regex
string outLine = null;
lock (ReplacementFinderRegex)
{
outLine = ReplacementFinderRegex.Replace(inLine, replacementMethodDelegate);
}
// Write the line to output stream
if (outLine != null)
outStreamWriter.WriteLine(outLine);
}
}
}
}
#endregion
}