1

I was searching the web but failed to find the correct example.

The goal is to have a function:

private void InsertLine(string source, string position, string content)

And write to a file using the StreamWriter so you do not need to read all lines because I the file is potentially huge.

My function so far:

    private void InsertLine(string source, string position, string content)
    {
        if (!File.Exists(source))
            throw new Exception(String.Format("Source:{0} does not exsists", source));

        var pos = GetPosition(position);
        int line_number = 0;
        string line;
        using (var fs = File.Open(source, FileMode.Open, FileAccess.ReadWrite))
                {
                    var destinationReader = new StreamReader(fs);
                    var writer = new StreamWriter(fs);
                    while (( line = destinationReader.ReadLine()) != null)
                    {
                      if (line_number == pos)
                        {
                            writer.WriteLine(content);
                            break;
                        }                            
                        line_number++;
                    }
                }
    }

The function does not work in the file as nothing happens.

Timmoth
  • 480
  • 2
  • 18
Jester
  • 3,069
  • 5
  • 30
  • 44
  • 2
    I don't think it would be possible to "insert" a line without reading and writing back out the remaining lines of the file. A text file is not simply a set of linked lines, everything after that point will need to be shifted. – Glen Thomas Mar 29 '16 at 11:03
  • And you are fortunate that _nothing happens_ because your code will truncate the file to a single line. What is the code of that GetPosition? It is puzzling. – Steve Mar 29 '16 at 11:04
  • Did you debug your code and check that it actually reaches line : writer.WriteLine(content); – Eminem Mar 29 '16 at 11:11
  • also wrap var writer = new StreamWriter(fs); in a using line i.e. using(var writer = new StreamWriter(fs)) {} – Eminem Mar 29 '16 at 11:12

1 Answers1

4

You can't just insert a line into a file. A file is a sequence of bytes.

You need to:

  • Write all of the preceding lines
  • Write the line to be inserted
  • Write all of the following lines

Here's some untested code based upon yours:

private void InsertLine(string source, string position, string content)
{
    if (!File.Exists(source))
        throw new Exception(String.Format("Source:{0} does not exsists", source));

    // I don't know what all of this is for....
    var pos = GetPosition(position);
    int line_number = 0;
    string line;

    using (var fs = File.Open(source, FileMode.Open, FileAccess.ReadWrite))
    {
        var destinationReader = new StreamReader(fs);
        var writer = new StreamWriter(fs);
        while (( line = destinationReader.ReadLine()) != null)
        {
            writer.WriteLine(line);    // ADDED: You need to write every original line

            if (line_number == pos)
            {
                writer.WriteLine(content);
                // REMOVED the break; here. You need to write all following lines
            }

            line_number++;    // MOVED this out of the if {}. Always count lines.

        }

    }
}

This probably won't work as expected, however. You're trying to write to the same file you're reading. You should open a new (temporary) file, perform the copy + insert, and then move/rename the temporary file to replace the original file.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • I've in mind something telling me what *write all of the preceding lines* is [optional](http://stackoverflow.com/q/4573604/1997232). It may be important performance-wise when dealing with big files. – Sinatr Mar 29 '16 at 11:10
  • @Sinatr Excellent point. I was trying to simply modify the OP code to demonstrate what it is doing wrong. Perhaps this question would be better closed as a duplicate of the one you've linked. – Jonathon Reinhart Mar 29 '16 at 11:12
  • I do understand what you mean but by this concept would still need to read trough the entire file. Can that be done with something like seek or that kind of technique? – Jester Mar 29 '16 at 11:58
  • Follow the link that sinatr posted above. – Jonathon Reinhart Mar 29 '16 at 12:10