0

i'm working in a .NET Framework 4.8 Environment where i want to read the last line of a text file, similiar to a log file. As the file is continously growing i need to ocassionaly read the last line programatically.

I created a "tail"-like script, which will read the whole file by line as a string array and return X amount of lines from the end.

dim filePath = "C:\file.xy"
dim linesCount = 5 'amout of lines i want to read

dim lines = File.ReadAllLines(filePath)
dim startLineIndex = lines.length - linesCount

for index = startLineIndex to lines.length - 1
    dim value = lines(index)
    result = result & cstr(value) & Environment.NewLine
next

This naive take on a tail function will get slower, the longer the file gets. How can i receive the last lines of the file without reading the whole document before?

thanks for helping me out!

TheDomis4
  • 122
  • 1
  • 13
  • 1
    Related: [Most effective way to periodically read last part of a file](https://stackoverflow.com/q/16319228/205233) – Filburt Aug 25 '21 at 10:59
  • You can't use the File class, you need to open the file with FileShare.ReadWrite to permit the other process to append lines to the file. Use FileStream to open the file, Seek() to a position for which you can be pretty sure you can still read 5 lines. So (say) Length - 6*100. Use the StreamReader(Stream) constructor to start reading. – Hans Passant Aug 25 '21 at 11:53

1 Answers1

0

This would work reliably:

dim filePath = "C:\file.txt"

Dim lastLine As String = File.ReadLines(filePath).Last()

This streams line per line (thank you @jmcilhinney), unlike ReadAllLines, which stores the whole file as string array. Unless your file is unreasonably large (100k lines for example), this would your best option.


Reference from this webpage:

File.ReadAllLines stores the entire file contents in a String array. File.ReadLines does not.

This question led me down a rabbit hole of answers from @Jon Skeet:

Joe Moore
  • 2,031
  • 2
  • 8
  • 29
  • 1
    That code does read the whole file in that instance. It just doesn't store the whole file. `ReadLines` reads the file line by line and makes each line available to process before reading the next, while `ReadAllLines` reads the whole file first, before making the data available. Your code still reads each line but discards all but the last. It's still probably the way to go, unless the file is very big, but it's best to understand what it's actually doing. If the file is very big, you're better to search from the end for a line break in the binary data and then read text from there. – jmcilhinney Aug 25 '21 at 11:40
  • @jmcilhinney Added that correction in, thanks for putting that into perspective. – Joe Moore Aug 25 '21 at 12:56