August 15th, 2007

How Can I Combine Lines in a Text File?

Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I combine lines in a text file?

— JN

SpacerHey, Scripting Guy! AnswerScript Center

Hey, JN. So you need to know how to combine lines in a text file, huh? Well, to tell you the truth, we’re kind of in a hurry today; the Scripting Guy who writes this column is getting ready to head out to St. Peter’s and the Sistine Chapel. But tell you what: we don’t have to leave for a few minutes, so we’ll see what we can do.

Note. Before you ask, yes, it is just a coincidence that the Scripting Guy who writes this column is visiting the Vatican just days before he gets back the results of the past year’s performance review. Not that he’s opposed to using prayer for personal gain, mind you. It’s just that if this review goes anything at all like his last one did, well, needless to say, in that case even divine intervention isn’t going to help him much.

OK, let’s see … combine two lines in a text file. How in the world can we – oh, wait: we have an idea. One of the great things about traveling is that you have the opportunity to learn little-known facts about famous people. Take Michelangelo, for example. Most people know Michelangelo as the designer of St. Peter’s dome, the sculptor of the Pieta, and the painter of the Sistine Chapel. What most people don’t know, however, is that, before becoming an artist, Michelangelo worked as an apprentice script writer. That’s pretty cool; even cooler is the fact that one of the scripts he wrote during that time goes out and combines lines in a text file. Having photocopied a manuscript from the Vatican library, the Scripting Guy who writes this column is pleased to present Michelangelo’s solution to the problem of combining lines in a text file:

Const ForReading = 1
Const ForWriting = 2

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

Do Until objFile.AtEndOfStream strLine1 = objFile.ReadLine strLine2 = objFile.ReadLine strNewLine = strLine1 & strLine2 strNewContents = strNewContents & strNewLine & vbCrLf Loop

objFile.Close

Set objFile = objFSO.OpenTextFile(“C:\Scripts\Test.txt”, ForWriting) objFile.Write strNewContents objFile.Close

And some people think that the Sistine Chapel ceiling is Michelangelo’s finest creation. Ha! The Scripting Guy who writes this column isn’t ashamed to admit that he cried from sheer joy the first time he saw this code for combining lines in a text file. Beautiful, just beautiful.

Before we explain how Michelangelo’s code works, we should take a moment to discuss JN’s situation in a little more detail. JN has a text file that looks like this:

SID123456
789
SID234567
891
SID345678
912
SID456789
123

Yes, that is a nice little text file, isn’t it? Unfortunately, however, things are all messed up; somehow or another, the last three characters in each line got put on a separate line. In reality, the text file is supposed to look like this:

SID123456789
SID234567891
SID345678912
SID456789123

In this example, that means four lines of text, not eight lines.

Hey, why the long face? Listen, there’s no need to despair: not only can we repair this broken text file but, as you’re about to see, we can do this with a minimal amount of effort.

So how do we fix JN’s text file? Well, Michelangelo solved the problem by first defining a pair of constants, ForReading and ForWriting; as most of you know by now, these two constants will be deployed when we go to open the text file. (And, as most of you also know by now, we need to open this file twice: once to read in the existing contents, and a second time to write out the modified contents.) After defining the two constants we create an instance of the Scripting.FileSystemObject object, then use this line of code to open the file C:\Scripts\Test.txt for reading:

Set objFile = objFSO.OpenTextFile(“C:\Scripts\Test.txt”, ForReading)

Our next task involves reading the existing contents of the file, line-by-line. To do that, we first set up a Do Until loop that runs until we’ve reached the end of the file (that is, until the file’s AtEndOfStream property is True). Inside the loop, we call the ReadLine method to read the first line of the file and store it in a variable named strLine1:

strLine1 = objFile.ReadLine

We then immediately call the ReadLine method again, thus reading the second line in the file and storing that value in a variable named strLine2:

strLine2 = objFile.ReadLine

What’s the point of all that? Well, strLine1 is now equal to SID123456 and strLine2 is now equal to 789. Guess what you get if you concatenate these two values? Good guess:

SID123456789

That, needless to say, is the very value we were hoping to get. With that in mind, we use this line of code to combine the two values and store the new string in variable named strNewLine:

strNewLine = strLine1 & strLine2

The net result is that we now have a new and improved line 1 for our file. Therefore, we use this line of code to append the new line (plus a carriage return-linefeed) to the variable strNewContents:

strNewContents = strNewContents & strNewLine & vbCrLf

We then loop around and repeat this process by combining lines 3 and 4 in the text file, and then appending that value to strContents as well. By the time we exit the loop, the variable strContents will be equal to this:

SID123456789
SID234567891
SID345678912
SID456789123

At that point we call the Close method to close the text file, then immediately reopen the same file, this time for writing:

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

As soon as the file is open, we use the Write method to replace the existing contents of Test.txt with the value of the variable strNewContents:

objFile.Write strNewContents

From there we close the file one final time and we’re done. Like we said, sheer genius.

Note: We should note that this script works only if the file has an even number of lines in it, which will always be the case in the example JN asked about. However, if you happen to have an extra line at the end of the file, the script will crash:

C:\scripts\hey0814.vbs(9, 5) Microsoft VBScript runtime error: Input past end of file

To avoid this, you can set up your script to check for the end of the file before it reads the second line, like this:

Const ForReading = 1
Const ForWriting = 2

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

Do Until objFile.AtEndOfStream strLine1 = objFile.ReadLine strLine2 = “” If Not objFile.AtEndOfStream Then strLine2 = objFile.ReadLine End If strNewLine = strLine1 & strLine2 strNewContents = strNewContents & strNewLine & vbCrLf Loop

objFile.Close

Set objFile = objFSO.OpenTextFile(“C:\Scripts\Test.txt”, ForWriting) objFile.Write strNewContents objFile.Close

Notice we added an If statement inside our Do Until loop. After reading in strLine1, we then clear the contents of strLine2 then check to see if the last line we read was the last one in the file. If it was, we simply bypass the next ReadLine and create the new line (strNewLine) with the contents of strLine1 and the empty strLine2. If we’re not at the end of the file, we read in strLine2.

We should probably note that, in all fairness, the Scripting Guy who writes this column doesn’t know as much about Michelangelo as he probably should. (Although he does know – or at least as he knows now, anyway – that this is the not same Michelangelo as the one from the Teenage Mutant Ninja Turtles.) He also knows that Michelangelo’s love of beauty didn’t extend to himself: he dressed poorly, ate even worse, and never bathed. (No, never.) Michelangelo was also a bit … eccentric. According to one story, after finishing his sculpture of Moses, Michelangelo took a hammer and whacked the statue on the knee, demanding, “Why don’t you speak to me?!?” OK ….

On top of all that, Michelangelo was also prone to bouts of depression. Towards the end of his life he noted that:

“I live alone and miserable, trapped as marrow under the bark of the tree …. Poor, old, beaten, I will be reduced to nothing, if death does not come swiftly to my rescue. Pains have quartered me, torn me, broken me and death is the only inn awaiting me.”

Sounds like just another day at the office for the Scripting Guys.

Author

0 comments

Discussion are closed.