How Can I Reverse All the Lines in a Text File?

How Can I Reverse All the Lines in a Text File?

  • Comments 3
  • Likes
Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I “rotate” a text file 180 degrees? I need the last line in the file to become the first line, the first line in the file to become the last line, and all the lines in between to switch places as well.

-- BJM

SpacerHey, Scripting Guy! AnswerScript Center

Hey, BJM. You know, when most people think of the Scripting Guys they think, “OK, sure, those guys are absolute geniuses when it comes to system administration scripting. But that just means they’re a bunch of geeks; I bet they aren’t well-rounded intellectuals who know the slightest thing about anything besides system administration scripting.” But you want to know the truth? The truth is, we Scripting Guys are – what’s that? Who said that the Scripting Guys are absolute geniuses when it comes to system administration scripting? Well, you know, there was that one guy, the one who always wears the blue shirt. Oh, and the girl in the green baseball hat; she said we were absolute something-or-others (probably “absolute geniuses,” although it was kind of hard to hear her over all the screaming). And, well, needless to say, far more people than we could possibly list in today’s column.

Far more.

Anyway, the point is that … wait a second here … the point is that …hold on a second…. The point is that the Scripting Guys are well-rounded intellectuals, that we are people who know about things other than system administration scripting. For example, the moment we saw BJM’s question, the one about making the last line in a text file the first line and the first line in a text file the last line, well, we immediately thought of the parable of the vineyards: “So the last will be first and the first will be last.” That sounds pretty well-rounded to us.

Of course, we didn’t exactly know what to do with that phrase, nor did we have any idea how we could relate that parable to system administration scripting. In other words, we had a tiny, isolated piece of knowledge that had no practical application whatsoever. But if that’s not a definition of an intellectual, well, we don’t what is!

So we admit it: we’re not sure what the parable of the vineyards has to do with rotating the lines in a text file. (Although we do think tossing a famous quote into a column every now and then sure makes it sound like we know what we’re talking about.) On the other hand, we are sure that the following script has a bit more relevance to the job of reversing all the lines in a text file.

Well, pretty sure, anyway. Here’s the script:

Const ForReading = 1
Const ForWriting = 2

Dim arrLines()
i = 0

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForReading)

Do Until objFile.AtEndOfStream
    Redim Preserve arrLines(i)
    arrLines(i) = objFile.ReadLine
    i = i + 1
Loop

objFile.Close

Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForWriting)

For i = Ubound(arrLines) to LBound(arrLines) Step -1
    objFile.WriteLine arrLines(i)
Next

objFile.Close

As you can see, we start out by defining a pair of constants (ForReading and ForWriting), constants we’ll need when we open the text file to be “rotated.” After defining the two constants we then use this line of code to declare a dynamic array named arrLines:

Dim arrLines()

Once the array has been declared we set the value of a counter variable i to 0.

Note. What’s that? What’s a “dynamic array?” Well, in VBScript, a plain old array is an array of a fixed size; in advance, you must specify that the array will hold, at most, 10 or 12 or 15 or whatever number of items. By contrast, a dynamic array is, well, a bit more dynamic: it can end up being any size, and can be resized on-the-fly to accommodate new items. We need a dynamic array here for one simple reason: we’re going to use the array to store all the lines we read in from the text file and, because we have no idea how many lines are actually in the text file, well, that means that we can’t specify the size of the array in advance. That leaves just one option: a dynamic array.

Our next step is to create an instance of the Scripting.FileSystemObject object, then use the OpenTextFile method to open the file C:\Scripts\Test.txt for reading; that’s what we do with these two lines of code:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForReading)

In turn, that brings us to the following section of the script:

Do Until objFile.AtEndOfStream
    Redim Preserve arrLines(i)
    arrLines(i) = objFile.ReadLine
    i = i + 1
Loop

What we’re doing here is setting up a Do Until loop that runs until we’ve read the entire text file (that is, until the file’s AtEndOfStream property is True). Inside the loop, the very first thing we do is execute this line of code:

Redim Preserve arrLines(i)

As it turns out, the Redim Preserve statement is the key to resizing our dynamic array. The Redim statement is used to change the size of the array; meanwhile, the Preserve statement tells the script to be sure and preserve any existing data in the array. That, by the way, is very important. Suppose we left out the Preserve statement and executed this line of code instead:

Redim arrLines(i)

What would happen in that case? Well, in that case our array would be resized. However, any existing items in the array would be deleted, and we’d be left with an empty array of size i.

Which reminds us: notice that we use the counter variable i to indicate the size of the array. Because i is currently equal to 0, that means that, the first time through the loop, we’ll end up with an array named arrLines that has a size of 0. (Which means that the array can hold one item: an array always holds one more item than the size would seem to indicate. That’s because the first item in an array is always given the index number 0.)

So what happens once we have an array of size 0? Well, our next step is to use the ReadLine method to read the first line in the text file, then assign that value to item 0 in the array. That’s what we do here:

arrLines(i) = objFile.ReadLine

We then increment the value of i by 1. That means that, the second time through the loop, i will be equal to 1. In turn, that means we’ll resize the array to a size of 1 (meaning the array can now hold 2 items), then we’ll read the next line in the text file and assign that value to the second item in the array (the item with the index number 1). This process then continues until we’ve read and processed each and every line in the text file, at which point we automatically exit the Do Until loop. As soon as that happens we use the Close method to close the file C:\Scripts\Test.txt.

So what does all this mean? This means that the array arrLines now contains the individual lines in the text file, lines that we’ll assume look like this:

E. This is line 5.
D. This is line 4.
C. This is line 3.
B. This is line 2.
A. This is line 1.

In other words, arrLines is now the spitting image of the file C:\Scripts\Test.txt.

At this point we’re ready to rotate the text file. As it turns out, VBScript doesn’t include a function for rotating a text file; however, VBScript does include a procedure for reading an array from the bottom to the top. That’s the approach we’re going to use to reverse the lines in the file.

To that end, our next step is to reopen the file C:\Scripts\Test.txt, this time for writing:

Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForWriting)

As soon as the file has been reopened, we execute this block of code:

For i = Ubound(arrLines) to LBound(arrLines) Step -1
    objFile.WriteLine arrLines(i)
Next

What we’re doing here is reading the array from the bottom to the top: we’re starting with the Ubound item (the last item in the array) and then finishing with the Lbound item (the first item in the array). In other words, our For Next loop is starting with item 4 (remember, in a 5-item array like ours the very last item has an index number of 4) and finishing with item 0 (because the first item in an array always has the index number 0). We use the statement Step -1 to ensure that our loop runs backwards: item 4, item 3, item 2, item 1, item 0.

Inside the loop, we simply use the WriteLine method to write the value of the current array item (item 4 the first time through the loop) to the text file. This continues until we’ve accessed each item in the array, at which point we exit the loop, close the file, and then take off to pursue more intellectual pastimes.

Like watch yet another edition of Baseball Tonight on ESPN.

So what’s the net effect of all this? This is the net effect:

A. This is line 1.
B. This is line 2.
C. This is line 3.
D. This is line 4.
E. This is line 5.

As you can see, we’ve successfully rotated our text file: the first is now last, the last is now first, and everything in between has been shuffled around accordingly. Which is just the way we wanted things to be shuffled.

There you have it, BJM. Incidentally, we know that you had another question about text files. But don’t worry; we’ll address that question in the near future. For now, however, we need to clarify one thing: upon double-checking our sources, it turns out that the parable of the vineyards does not include the phrase “So the last will be first and the first will be last.” Instead, the correct translation is actually “So the last will be first and the Scripting Guys will be last.” Which, needless to say, is something we’ve known for a long time.

Or at least since last year’s performance review.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Thanks! This is exactly what I was looking for.

  • Hi there.  This whole thing has me very confused.  I am trying to run this in powershell and it seems like the syntax just doesn't work and I am not sure why.  Is this actually written in powershell?   When I search for objFile.AtEndofStream it tells me it is VB.. when I try and run the script.. it tells me it expects a funtion after Dim arrlines ( so I changed it to Dim arrLines (0).  Then it said that it expected a function after the comma in this statment.  Set objFile = objFSO.OpenTextFile("C:\TEST\TESTFile.txt", ForReading).  

    What am I doing wrong?  Is this script in Powershell or VB? Really really confused and trying to learn here.

  • @Matt - not PowerShell.  Look at the date on the post.