Search code examples
c#iolines

C# Search file for a string and get the string's line number


I've been at this all day and I'm struggling to do it, I've searched far and wide and though there are similar questions, there are no answers.

What I'm trying to do: I'm trying to search a file for multiple strings and receive the line numbers so that when users wish to change said strings inside my application, my application knows what lines to replace with their string.

What I've tried so far: I've tried the below code, my attempt was to read the file then receive the line number, however it doesn't seem to be working at all.

            var lines = File.ReadAllLines(filepath);
            foreach (var match in lines // File.ReadLines(filePath)
                            .Select((text, index) => new { text, lineNumber = index + 1 })
                            .Where(x => x.text.Contains("motd=")))
            {
                lines[match.lineNumber] = "motd=" + textBox1.Text;
                File.WriteAllLines(filepath, lines);
            }
        }

What I expect the above code to do is find the string "motd=" in the file, get the line number and attempt to re-write it with what the user has inputted.

However, I receive this error: "Index was outside the bounds of the array".


Solution

  • I think a for loop makes more sense here

    var lines = File.ReadAllLines(filepath);
    for (int i = 0; i < lines.Length; i++)
    {
        if(lines[i].Contains("motd="))
        {
            lines[i] = "motd=" + textBox1.Text;
        }
    }
    
    File.WriteAllLines(filepath, lines);
    

    A couple of issues with your code was that you were writing out the file in side the loop and you incremented the index by 1 which would then point to the wrong line in the array and result in the exception you are getting if the last line contains the text you are searching for.

    It should be noted that this could be a memory hog if you are working with a really large file. In that case I'd read the lines in one at a time and write them out to a temp file, then delete the original file and rename the temp at the end.

    var tempFile = Path.GetTempFileName();
    using (var file = File.OpenWrite(tempFile))
    using (var writer = new StreamWriter(file))
    {
        foreach (var line in File.ReadLines(filepath))
        {
            if (line.Contains("motd="))
            {
                writer.WriteLine("motd=" + textBox1.Text);
            }
            else
            {
                writer.WriteLine(line);
            }
        }
    }
    
    File.Delete(filepath);
    File.Move(tempFile, filepath);