Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace a character of the nth position

Tags:

c#

asp.net

I am writing this program to replace the character at the nth position of a string in a text file. My text file consists of the following contents -

the quick brown fox jumped over the lazy dog
the quick brown fox jumped over the lazy dog
the quick brown fox jumped over the lazy dog
the quick brown fox jumped over the lazy dog

And here is the output of the code -

thehuick brown fox jumped over the lazy dog

The above result is not what i wanted. Only one line is updated the rest are not found anymore within the file.

Here's my complete code in C#

        var txtFiles = Directory.GetFiles(@"E:\PROJ\replaceY\replaceY\", "*.txt");
        foreach (string currentFile in txtFiles)
        {
            string[] lines = File.ReadAllLines(currentFile);
            foreach (string line in lines)
            {

                var theString = line;
                var aStringBuilder = new StringBuilder(theString);
                aStringBuilder.Remove(3, 2);
                aStringBuilder.Insert(3, "h");
                theString = aStringBuilder.ToString();
                using (StreamWriter outfile = new StreamWriter(currentFile))
                {
                    outfile.Write(theString.ToString());
                }

                Console.WriteLine(theString);
                Console.ReadKey();

            }
        }

Where have i gone wrong? Please help!

like image 655
shaiToro Avatar asked Jul 27 '15 20:07

shaiToro


People also ask

How do you change the nth character in Excel?

To replace the first n characters with another string, you just need the Replace function. Select a cell you will place the formula, and type this =REPLACE(A1,1,3,"KTE"), then drag fill handle over the cells you need.


3 Answers

Because your logic says:

  • for each file
    • open the file
    • for each line in the file
      • process it
      • re-open the file for write
      • write the line

That means you repeatedly overwrite the file with the latest line. At the end of it all each file contains just one line: the last one.

You'll be wanting to do something like this:

static void Main(string[] args)
{
  foreach ( string fileName in args )
  {
    string tempFileName = Path.GetTempFileName() ;

    using ( Stream       tmpFile = File.Open( tempFileName , FileMode.OpenOrCreate , FileAccess.Write , FileShare.None ) )
    using ( StreamWriter output = new StreamWriter( tgtFile , Encoding.Default ) )
    using ( Stream       srcFile = File.Open( fileName , FileMode.Open , FileAccess.ReadWrite , FileShare.None ) )
    using ( StreamReader input = new StreamReader( srcFile , Encoding.Default , true ) )
    {
      string line ;
      while ( null != (line=input.ReadLine()) )
      {
        output.Write( line.Substring(0,3) ) ;
        output.Write( 'h' ) ;
        output.WriteLine( line.Substring(5) ) ;
      }
    }

    string backupFileName = string.Format( "{0}.{1:yyyy-MM-dd.HHmmss}.bak" , fileName , DateTime.Now ) ;

    File.Move( fileName     , backupFileName ) ;
    File.Move( tempFileName , fileName ) ;
    File.Delete( backupFileName ) ;

  }
  return;
}

You'll need to add some try/catch/finally exception handling to deal with cases where something goes south with a file, so you can roll that file back to its original state.

The other options is to

  • open the file for read.
  • slurp in the entire contents with File.ReadAllLines() or the equivalent
  • transform the lines as you see fit
  • re-open the original file for write
  • spit the transformed contents out into the original file.

Which brings you to something like this:

static void Main(string[] args)
{
  foreach ( string fileName in args )
  {
    string[] lines = File.ReadAllLines( fileName ) ;

    for ( int i = 0 ; i < lines.Length ; ++i )
    {
      lines[i] = ApplyTransformHere( lines[i] ) ;
    }

    File.WriteAllLines( fileName , lines ) ;

  }

  return;
}
like image 91
Nicholas Carey Avatar answered Oct 16 '22 08:10

Nicholas Carey


I created a boolean append at the beginning of every new file that is set to false, so it creates a new file for the first line, then sets append = true so each subsequent line is appended on

var txtFiles = Directory.GetFiles(@"E:\PROJ\replaceY\replaceY\", "*.txt");
foreach (string currentFile in txtFiles)
{
    var append = false;
    string[] lines = File.ReadAllLines(currentFile);
    foreach (string line in lines)
    {
        var theString = line;
        var aStringBuilder = new StringBuilder(theString);
        aStringBuilder.Remove(3, 2);
        aStringBuilder.Insert(3, "h");
        theString = aStringBuilder.ToString();
        using (StreamWriter outfile = new StreamWriter(currentFile, append))
        {
            outfile.Write(theString.ToString() + Environment.NewLine);
        }
        append = true;
    }
}
like image 3
Cole9350 Avatar answered Oct 16 '22 10:10

Cole9350


On a side note but still related. Have you consider using Regex to replace all lines?

https://regex101.com/r/aC6cY1/1

Like /(?<=^.{4,4})./gm

string input = "";//your sample text above
string pattern = "(?<=^.{4,4}).";
string replacement = "h";
Regex rgx = new Regex(pattern, RegexOptions.Multiline);
string result = rgx.Replace(input, replacement);

Regarding your issue I would:

var txtFiles = Directory.GetFiles(@"E:\PROJ\replaceY\replaceY\", "*.txt");
        foreach (string currentFile in txtFiles)
        {
        using (StreamReader sr = new StreamReader(currentFile))
            {
                 string input = sr.ReadToEnd();
                 string pattern = "(?<=^.{4,4}).";
                 string replacement = "h";
                 Regex rgx = new Regex(pattern, RegexOptions.Multiline);
                 string result = rgx.Replace(input, replacement);
                 using (StreamWriter outfile = new StreamWriter(currentFile, append))
                  {
                      outfile.Write(result);
                  }
            }
}
like image 2
Dalorzo Avatar answered Oct 16 '22 09:10

Dalorzo