Hey, Scripting Guy! How can I read just the last line of a text file?
— BM
Hey, BM. You know, if you’ve ever wondered how Hey, Scripting Guy! differs from other daily columns (like, say, Dear Abby), well, here’s one way. Suppose someone writes Dear Abby and says this:
Dear Abby:
My life is all messed up and I need to do something about it. How can I turn my life around and be happy again?
Desperate in Dayton
Most likely Dear Abby would never give Desperate an answer like this:
Dear Desperate:
Well, you can’t. Sorry.
So how do you think the Scripting Guys will answer your question about reading just the last line of a text file? You got it:
Dear BM:
Well, you can’t. Sorry.
But wait, don’t go yet. It’s true that Dear Abby would never say, “You know, Desperate, I can’t help you become happy. But here’s a workaround that will make it look like you’re happy.” The Scripting Guys, however, have no such qualms. In other words, we can’t give you a script that reads just the last line of a text file. But here’s a script that will make it look like you read just the last line of a text file:
Const ForReading = 1Set objFSO = CreateObject(“Scripting.FileSystemObject”) Set objFile = objFSO.OpenTextFile(“C:\Scripts\Test.txt”, ForReading)
Do Until objFile.AtEndOfStream strLine = objFile.ReadLine Loop
objFile.Close
Wscript.Echo strLine
The problem we’ve run into here is that the FileSystemObject (the scripting object used to work with text files) knows only one direction: forward. It has to start at the beginning of a file, and it can only continue on towards the end of that file. You can’t specify an alternate starting location and you can’t read backwards (from the end to the beginning). In fact, you can’t even re-read a file: if you reach the end there’s no way to start all over except by closing and re-opening the file. That’s why workarounds are pretty much par for the course when it comes to text files.
The workaround here is that we actually do read the entire script from beginning to end. However, we keep track of only the very last line we’ve read. When we reach the end of the file, we’ll have a variable that contains the value of the last line read; that will also be the last line in the file. When we echo back the value of that variable it will look like we read only the last line (especially because, if nothing else, the FileSystemObject is pretty fast). We didn’t – we actually read the entire file – but no one will ever know. It’ll be our little secret.
As for the code itself, we begin by defining a constant named ForReading and setting the value to 1; we’ll use this constant to tell the FileSystemObject that we want to open a file for reading. We then create an instance of the Scripting.FileSystemObject, and use the OpenTextFile method to open the file C:\Scripts\Test.txt. That brings us to this block of code:
Do Until objFile.AtEndOfStream strLine = objFile.ReadLine Loop
All we’re doing here is reading the file, line by line, until we reach the end (that is, until we’re at the end of the file stream). Each time we read in a line we replace the value of the variable strLine with the text we just read. For example, suppose our text file consists of three lines:
A B C
Inside our loop we read in line 1, and thus assign the value A to strLine. We loop around and read the second line, meaning the value B gets assigned to strLine. We loop around again and assign the value C to strLine. Because we’ve reached the end of the file strLine retains the value C, which just happens to be the last line in the file. We then close the file and echo the value of strLine. As far as anyone knows, all we did was read – and report back – the value of the last line in the file.
Yes, very sneaky.
Admittedly, there’s one potential problem with this script. Suppose you have a file that has several blank lines tacked on to the end. Our script will dutifully report back nothing (a blank value) as the last line in the text file. That’s what it should do: after all, the last line in the file is blank. But suppose this is a log file of some type and, for whatever reason, the application that creates this log always throws a few blank lines onto the end of the file. In that case what you’re probably really interested in is the last non-blank line in the file. Here’s a modified version of the script that uses the Len function to check the length of each line that’s read in. If the length is equal to 0, that means it’s a blank line, and the value is not stored in the variable strLine:
Const ForReading = 1Set objFSO = CreateObject(“Scripting.FileSystemObject”) Set objFile = objFSO.OpenTextFile(“C:\Scripts\Test.txt”, ForReading)
Do Until objFile.AtEndOfStream strNextLine = objFile.ReadLine If Len(strNextLine) > 0 Then strLine = strNextLine End If Loop
objFile.Close
Wscript.Echo strLine
Eat your heart out, Dear Abby!
0 comments