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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
// 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 } |