Search code examples
c#file-ioappendtext

Appending to new line will not go to new line


I am trying to append the text from a text box to a new line in a text file and have run into an issue. Lets say that there are already contents in the text file and looks something like this

something
Something
Something<---- Cursor ends here

And the cursor ends where the arrow is pointing (After the g on the last 'something'. If I try to use

File.AppendAllLines(@"Location", new[]{tb.Text});

Or

File.AppendAllText(@"Location", tb.Text + Environment.NewLine);

They will put the text where the cursor is at, not on a new line under the last item in the text file. It works if the cursor is on a new line to begin with but as soon as it ends at the end of the word everything goes on the same line.

Is there something I'm missing? Would using a streamwriter or some other method fix this issue?


Solution

  • Actually, as pointed out in other answers. This is by design. File.AppendAllLines appends text at the end of the file. It does not add a line break before appending text. For this, you will have to read the file somehow and determine if the last character is a line break. There are multiple ways to do this.

    The simplest way is to just read all lines and check if the last line is empty. If not, just prepend a line break to your string before passing it to File.AppendAllLines.

    However, if dealing with large files, or if you do not want to open the file multiple times - something like the following method will do this whilst still only opening the file once.

    public void AppendAllLinesAtNewLine(string path, IEnumerable<string> content)
    {
        // No file, just append as usual.
        if (!File.Exists(path))
        {
            File.AppendAllLines(path, content);
            return;
        }
    
        using (var stream = File.Open(path, FileMode.Open, FileAccess.ReadWrite))
        using (var reader = new StreamReader(stream))
        using (var writer = new StreamWriter(stream))
        {
            // Determines if there is a new line at the end of the file. If not, one is appended.
            long readPosition = stream.Length == 0 ? 0 : -1;
            stream.Seek(readPosition, SeekOrigin.End);
            string end = reader.ReadToEnd();
            if (end.Length != 0 && !end.Equals("\n", StringComparison.Ordinal))
            {
               writer.Write(Environment.NewLine);
            }
    
            // Simple write all lines.
            foreach (var line in content)
            {
                writer.WriteLine(line);
            }
        }
    }
    

    Note: the long readPosition = s.Length == 0 ? 0 : -1; is for handling empty files.