Philip Adler
Philip Adler

Reputation: 2206

Read lines in C# without losing newline characters

At the moment, I am using C#'s inbuilt StreamReader to read lines from a file.

As is well known, if the last line is blank, the stream reader does not acknowledge this as a separate line. That is, a line must contain text, and the newline character at the end is optional for the last line.

This is having the effect on some of my files that I am losing (important, for reasons I don't want to get into) whitespace at the end of the file each time my program consumes and re-writes specific files.

Is there an implementation of TextReader available either as a part of the language or as a NuGet package which provides the ReadLine functionality, but retains the new line characters (whichever they may be) as a part of the line so that I can exactly reproduce the output? I would prefer not to have to roll my own method to consume line-based input.

Edit: it should be noted that I cannot read the whole file into memory.

Upvotes: 4

Views: 3813

Answers (2)

CSDev
CSDev

Reputation: 3235

private readonly char newLineMarker = Environment.NewLine.Last();
private readonly char[] newLine = Environment.NewLine.ToCharArray();
private readonly char eof = '\uffff';

private IEnumerable<string> EnumerateLines(string path)
{
    using (var sr = new StreamReader(path))
    {
        char c;
        string line;
        var sb = new StringBuilder();

        while ((c = (char)sr.Read()) != eof)
        {
            sb.Append(c);
            if (c == newLineMarker &&
                (line = sb.ToString()).EndsWith(Environment.NewLine))
            {
                yield return line.Trim(newLine);

                sb.Clear();
                sb.Append(Environment.NewLine);
            }
        }

        if (sb.Length > 0)
            yield return sb.ToString().Trim(newLine);
    }
}

Upvotes: 5

Cid
Cid

Reputation: 15247

You can combine ReadToEnd() with Split to get in an array the content of your file, including the empty lines.

I don't recommend you to use ReadToEnd() if your file is big.

In example :

string[] lines;

using (StreamReader sr = new StreamReader(path)) 
{
    var WholeFile = sr.ReadToEnd();
    lines = WholeFile.Split('\n');
}

Upvotes: 4

Related Questions