-2

I am writing a validation class to ensure valid files are being sent to 3rd party software. These files require a carriage return at the end but when I read them in to ensure that there is a carriage return at the end of the file the libraries I have used ignore the last line. If I put a space in this line it will read it but if I don't it gets ignored.

I've tried System.IO.File, FileStream.ReadLines, StreamReader, and StringReader using all the methods these classes have ReadAllLines(), ReadAllText(), ReadLines(), etc.

Anyone know of a way around this. I haven't managed to find anything so far.

Currently, this is the line of code I have

private void readfile()
{
    string[] lines = System.IO.File.ReadAllLines(filePath + file); 

     bool error  = ErrorValidatingLastLineOfFile(lines, lines.count());
}

private bool ErrorValidatingLastLineOfFile(string[] lines, int lastLine)
{
    if (lines[lastLine - 1] != "")
        return true;

    return false;
}

Example of file:

 1. [Section1]
 2. Error = 
 3. 
 4. [Section2]
 5. Error = 
 6.
 7. [Data]
 8. foo,bar,
 9.

numbers are lines on the file not acutally in file.

spaga
  • 153
  • 1
  • 3
  • 12
  • `ReadAllText` works and as you've stated you've tried that I suggest you show the code that checks to see if the file ends with `\n`, see how to create a [MCVE] for reference. – TheLethalCoder May 04 '17 at 10:55
  • You are reading *lines* which means each array item contains the *line* only, not the separator. A line without other content should return an empty string. Are you saying that the last array item is *not* an empty string? – Panagiotis Kanavos May 04 '17 at 10:55
  • No repro. Reading a file with empty lines, whether first or last, returns an empty string for each empty line – Panagiotis Kanavos May 04 '17 at 10:56
  • 2
    You have an off by **two** error. You pass `count()-1` then use `lastLine -1`. In effect, you check `count() -2` – Panagiotis Kanavos May 04 '17 at 11:05
  • 2
    Side note: `return (lines[lastLine - 1] != "");` is fine no need for the `if` with `return true;`.... – TheLethalCoder May 04 '17 at 11:05
  • sorry code has been copied over wrong – spaga May 04 '17 at 11:11

3 Answers3

2

Use System.IO.File.ReadAllText.

For example:

var text = System.IO.File.ReadAllText(filePath + file);
var isValid = text.EndsWith("\n");
Alex Warren
  • 7,187
  • 2
  • 31
  • 30
2

I can't reproduce this behaviour. ReadAllLines will return an empty string if a line doesn't contain anything:

File.WriteAllText("text.txt","a\n\n\n");
var lines=File.ReadAllLines("text.txt");

//The last line isn't ignored
Trace.Assert(lines.Length==3);

//The last line *is* empty
Trace.Assert(lines[2]=="");
Trace.Assert(lines[lines.Length -1]=="");
Trace.Assert(lines.Last()=="");

//So is any empty line
Trace.Assert(lines[2]=="");

The original code is checking the wrong line - instead of the last line (Length-1) it's checking the previous one ( (Length-1) -1), ie Length -2

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • Sorry code was copied over wrong but when i look into this array i am expecting 16 items from my file but there are only 15. I've used intellisense and last line has data in it when it should not. It should be empty. – spaga May 04 '17 at 11:13
  • My file is using \r not \n so if i change it will it still be readable from the other side? – spaga May 04 '17 at 11:18
  • I've notice that your answer is wrong you have 3 \n lines so the lines var should be of length 4 not 3. If you open this file in notepad++ it has 4 lines not 3. It is the last line (4th line) that I need here. – spaga May 04 '17 at 11:32
  • @spaga You misunderstood what you saw in Notepad++. There is no fourth line. Just because *Notepad++* shows an empty line after the last newline, doesn't mean there is a line there. Other editors *won't* display anything. In any case, your problem was that you were reading the wrong line – Panagiotis Kanavos May 04 '17 at 12:00
  • That was not the problem at all, as i have explained I copied the code over wrong. I was reading the right line. I have also checked with intellisense what values were in the array. In addition, I have opened the file your code created in sublime and vs code both of which show 4 lines not 3. – spaga May 04 '17 at 13:00
1

Maybe you need to check only CR (13) not full line ending (CR + LF which are 13 + 10). Then try this:

//read last char:
byte lastChar1 = System.IO.File.ReadAllBytes(filePath).Last();

//if a file is bigger, there is no need to read it all to just check the last char:
var fs = System.IO.File.OpenRead(filePath);
fs.Position = fs.Length-1;
var lastChar2 = fs.ReadByte();
fs.Close();

If last char is CR then it should be 13.

Ursula
  • 286
  • 2
  • 5
  • Actually, it's exactly the same answer as that postet by Johnny. `\n` *is* the byte 13 – Panagiotis Kanavos May 04 '17 at 12:04
  • From a table of ASCII codes: CR (carriage return) is 13 -> this is: \r LF (new line/line feed) is 10 -> this is: \n In Windows normally end of line are both chars in order: \r\n (CR + LF, 13 + 10). [here you can find more about it: http://stackoverflow.com/questions/1761051/difference-between-n-and-r] My answer was about \r (no: 13) and the other one about \n (no: 10). But a valid ansewr could be also: var isValid = text.EndsWith("\r"); – Ursula May 04 '17 at 13:04
  • @Ursula Both answers are right but your was better because it didn't require me to store the file in a variable. But yes, text.EndWith("\r") worked perfectly well. – spaga May 04 '17 at 13:07