Explanation
It is because you use readLine to check whether there is something to read and then again use readLine inside the loop.
So you actually read a line, reject it (inside the condition) and then read again a line. So every iteration you are reading two lines but only print one and you also only check for null with one of those two lines. That is why you see the print of null in the last iteration since there is no line left.
Considering your example:
name,add,sal // $1
john,SF,25k // $2
Roy,Chicago,30k // $3
jason,SF,35k // $4
joy,Sf,50K // $5
And your code:
System.out.println(getHeaderLine(f)); // #1
while (in.readLine() != null) { // #2
System.out.println(in.readLine()); // #3
}
Line #1 reads the head line $1 and prints it.
Then you create a new BufferedReader whose pointer is placed at the start of the file again, so the head line. Line #2 is executed which again reads the head line $1 and checks it for null. It is not null and the code starts the first loop iteration.
Line #3 is executed, reading and printing the second line $2. The loop checks again the condition in line #2, it reads the next line $3 and checks it for null.
It's not and line #3 gets executed which reads and prints line $4. The condition is checked again in line #2, thus it reads line $5 and checks it for null. It is again not null thus it continues.
Again line #3 is executed which reads and prints a line ($6). However as there is no line left anymore to read, it reads and prints null. The condition is checked again, trying to read a line ($7) but there is no, the loop terminates.
All in all we have printed line $1 (due to #1) and $2, $4, null (due to #3):
name,add,sal // $1
john,SF,25k // $2
jason,SF,35k // $4
null // ($6)
Which is exactly what you got.
Solution
You need to fix your logic. If you want to check whether there is something to read, don't read it, just check for it. Or alternatively read it, store it inside a variable and then check this variable.
while (true) {
// Read a line
String line = in.readLine();
if (line == null) {
// Abort, nothing to read anymore
break;
}
// Print what we have read
System.out.println(line);
}
Modern solution: NIO
However I recommend you to not use BufferedReader and this stuff for reading files anymore. Java has updated its I/O API, we now use NIO which revolves around the classes Path, Paths and Files. With NIO you print every line elegantly and platform independent like this:
Path fileToRead = Paths.get(System.getProperty("user.home"), "Desktop", "Abc.csv");
Files.lines(fileToRead).forEach(System.out::println);
That's all. Path substitutes the old File class. Paths and Files provide utility methods. Here are their documentations:
Fileanymore. Instead use the new modern NIO API of Java which revolves around the classesPaths,FilesandPath. With it you'll shrink your method to 1-2 lines. Also you should never forget to close your resources. Usereader.close()andin.close()if you are finished reading.