Yzj
Yzj

Reputation: 3

C# Replace a part of line and Write to new txt

Here the code that I create to replace some value at txt file. I want to replace the value 0 with 3 for lines which do not start with "#".

using (StreamWriter sr = new StreamWriter(@"D:\Testing\Ticket_post_test.txt"))
foreach(string line in File.ReadLines(@"D:\Testing\Ticket_post.txt"))
{
    string[] getFromLine = line.Split(' ');
    if (getFromLine[0].Equals("#") == false)
    {
        if (getFromLine[10].Equals("0") == true) ;
            (getFromLine[10]).Replace("0", "3");
    }
    sr.WriteLine(line);
}

Stuck at how to replace the 0 by 3 at line split[10] and write to a new txt file. The txt file show below

*#* start time = 2021-12-03-15-14-55

*#* end time = 2021-12-03-15-15-41

*#* name = SYSTEM

bot 10 pad 11 d 4 e 6 t #0 **0** 2021-12-03-15-14-55 # - 2021-12-03-15-15-41

bot 11 pad 12 d 5 e 7 t #0 **0** 2021-12-03-15-14-55 # - 2021-12-03-15-15-41

bot 12 pad 13 d 6 e 8 t #0 **1** 2021-12-03-15-14-55 # - 2021-12-03-15-15-41

and more

Upvotes: 0

Views: 101

Answers (2)

protoproto
protoproto

Reputation: 2099

I think this simple example will suit to your working problem.

using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;

namespace Stack5
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            ReadAndWriteTextFile();
        }

        private static void ReadAndWriteTextFile()
        {
            // Read text file
            // (?<string> ...) = name it with "string" name
            // ^(?!#) = select line not begin with "#"
            // (\S+\s){10} = bypass 10 group strings include a visible characters (\S) and a space (\s)
            string pattern = @"(?<one>^(?!#)(\S+\s){10})0(?<two>.+)";
            string substitution = @"${one}3${two}";
            Regex regex = new Regex(pattern);
            // Change the path to your path
            List<string> lines = File.ReadLines(@".\settings.txt").ToList();
            for (int i = 0; i < lines.Count(); i++)
            {
                // Check its value
                Debug.WriteLine(lines[i]);
                var match = Regex.Match(lines[i], pattern);
                if (match.Success)
                {
                    string r = regex.Replace(lines[i], substitution);
                    // Check its value
                    Debug.WriteLine("Change the line {0} to: {1}",i+1,r);
                    lines[i] = r;
                }

            }
            // Write text file
            File.WriteAllLines(@".\settings.txt",lines);
        }
    }
}

I tested it in my local machine, hope this helps you!

Ask me if you need, good to you good to me : D

Upvotes: 0

ProgrammingLlama
ProgrammingLlama

Reputation: 38785

Your code makes some erroneous assumptions, which I will correct here:

  1. When you split a string using .Split or .Substring, you are not creating a little window/little windows into the original string. You are producing altogether new strings.
  2. When you use .Replace, you are creating a new string with the altered values, not modifying the original in-place. See this question for more info on that.

This means that:

  1. Your replace is a no-op (it does nothing of any meaning).
  2. Your WriteLine is just writing the original line value back to the file without your changes.

We need to both fix your replace, and create the updated string to write to the file. As we are checking the value of getFromLine[10], we don't need .Replace at all, we can just set a new value:

using (StreamWriter sr = new StreamWriter(@"D:\Testing\Ticket_post_test.txt"))
{
    foreach (string line in File.ReadLines(@"D:\Testing\Ticket_post.txt"))
    {
        string[] getFromLine = line.Split(' ');
        if (getFromLine[0] != "#" && getFromLine[10] == "0")
        {
            getFromLine[10] = "3";
        }
        sr.WriteLine(String.Join(" ", getFromLine));
    }
}

This isn't especially efficient, but it should get the job done. You could potentially modify it like this to avoid creating a new string when no changes have been made:

using (StreamWriter sr = new StreamWriter(@"D:\Testing\Ticket_post_test.txt"))
{
    foreach (string line in File.ReadLines(@"D:\Testing\Ticket_post.txt"))
    {
        string[] getFromLine = line.Split(' ');
        if (getFromLine[0] != "#" && getFromLine[10] == "0")
        {
            getFromLine[10] = "3";
            sr.WriteLine(String.Join(" ", getFromLine));
        }
        else
        {
            sr.Write(line);
        }
    }
}

Note that you should probably also check the length of the array (i.e. if (getFromLine.Length >= 11 && getFromLine[0] != "#" && getFromLine[10] == "0") so that you don't get any IndexOutOfRangeException errors if you reach a line of the file that has less spaces than you expect (e.g. a blank line).

P.S. I've not tested this, so I've assumed that the rest of your logic is sound.

Upvotes: 2

Related Questions