{"id":64123,"date":"2007-08-30T01:45:00","date_gmt":"2007-08-30T01:45:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/08\/30\/how-can-i-reverse-all-the-lines-in-a-text-file\/"},"modified":"2007-08-30T01:45:00","modified_gmt":"2007-08-30T01:45:00","slug":"how-can-i-reverse-all-the-lines-in-a-text-file","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-reverse-all-the-lines-in-a-text-file\/","title":{"rendered":"How Can I Reverse All the Lines in a Text File?"},"content":{"rendered":"<p><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> \n<P>Hey, Scripting Guy! How can I \u201crotate\u201d 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.<BR><BR>&#8212; BJM <\/P><IMG height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" height=\"288\" alt=\"Script Center\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" align=\"right\" border=\"0\"><\/A> \n<P>Hey, BJM. You know, when most people think of the Scripting Guys they think, \u201cOK, sure, those guys are absolute <I>geniuses<\/I> when it comes to system administration scripting. But that just means they\u2019re a bunch of geeks; I bet they aren\u2019t well-rounded intellectuals who know the slightest thing about anything <I>besides<\/I> system administration scripting.\u201d But you want to know the truth? The truth is, we Scripting Guys are \u2013 what\u2019s that? <I>Who<\/I> 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 \u201cabsolute geniuses,\u201d although it was kind of hard to hear her over all the screaming). And, well, needless to say, far more people than we could <I>possibly<\/I> list in today\u2019s column.<\/P>\n<P>Far more.<\/P>\n<P>Anyway, the point is that \u2026 wait a second here \u2026 the point is that \u2026hold on a second\u2026. The point is that the Scripting Guys <I>are<\/I> well-rounded intellectuals, that we <I>are<\/I> people who know about things other than system administration scripting. For example, the moment we saw BJM\u2019s 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: \u201cSo the last will be first and the first will be last.\u201d That sounds pretty well-rounded to us.<\/P>\n<P>Of course, we didn\u2019t exactly know what to <I>do<\/I> 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 <I>that\u2019s<\/I> not a definition of an intellectual, well, we don\u2019t what is!<\/P>\n<P>So we admit it: we\u2019re not sure what the parable of the vineyards has to do with rotating the lines in a text file. (Although we <I>do<\/I> think tossing a famous quote into a column every now and then sure makes it <I>sound<\/I> like we know what we\u2019re talking about.) On the other hand, we <I>are<\/I> sure that the following script has a bit more relevance to the job of reversing all the lines in a text file.<\/P>\n<P>Well, pretty sure, anyway. Here\u2019s the script:<\/P><PRE class=\"codeSample\">Const ForReading = 1\nConst ForWriting = 2<\/p>\n<p>Dim arrLines()\ni = 0<\/p>\n<p>Set objFSO = CreateObject(&#8220;Scripting.FileSystemObject&#8221;)\nSet objFile = objFSO.OpenTextFile(&#8220;C:\\Scripts\\Test.txt&#8221;, ForReading)<\/p>\n<p>Do Until objFile.AtEndOfStream\n    Redim Preserve arrLines(i)\n    arrLines(i) = objFile.ReadLine\n    i = i + 1\nLoop<\/p>\n<p>objFile.Close<\/p>\n<p>Set objFile = objFSO.OpenTextFile(&#8220;C:\\Scripts\\Test.txt&#8221;, ForWriting)<\/p>\n<p>For i = Ubound(arrLines) to LBound(arrLines) Step -1\n    objFile.WriteLine arrLines(i)\nNext<\/p>\n<p>objFile.Close\n<\/PRE>\n<P>As you can see, we start out by defining a pair of constants (ForReading and ForWriting), constants we\u2019ll need when we open the text file to be \u201crotated.\u201d After defining the two constants we then use this line of code to declare a dynamic array named arrLines:<\/P><PRE class=\"codeSample\">Dim arrLines()\n<\/PRE>\n<P>Once the array has been declared we set the value of a counter variable i to 0.<\/P>\n<TABLE class=\"dataTable\" id=\"EJE\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Note<\/B>. What\u2019s that? What\u2019s a \u201cdynamic array?\u201d 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\u2019re 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 <I>in<\/I> the text file, well, that means that we can\u2019t specify the size of the array in advance. That leaves just one option: a dynamic array.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Our next step is to create an instance of the <B>Scripting.FileSystemObject<\/B> object, then use the <B>OpenTextFile<\/B> method to open the file C:\\Scripts\\Test.txt for reading; that\u2019s what we do with these two lines of code:<\/P><PRE class=\"codeSample\">Set objFSO = CreateObject(&#8220;Scripting.FileSystemObject&#8221;)\nSet objFile = objFSO.OpenTextFile(&#8220;C:\\Scripts\\Test.txt&#8221;, ForReading)\n<\/PRE>\n<P>In turn, that brings us to the following section of the script:<\/P><PRE class=\"codeSample\">Do Until objFile.AtEndOfStream\n    Redim Preserve arrLines(i)\n    arrLines(i) = objFile.ReadLine\n    i = i + 1\nLoop\n<\/PRE>\n<P>What we\u2019re doing here is setting up a Do Until loop that runs until we\u2019ve read the entire text file (that is, until the file\u2019s <B>AtEndOfStream<\/B> property is True). Inside the loop, the very first thing we do is execute this line of code:<\/P><PRE class=\"codeSample\">Redim Preserve arrLines(i)\n<\/PRE>\n<P>As it turns out, the <B>Redim Preserve<\/B> 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 <I>very<\/I> important. Suppose we left out the Preserve statement and executed this line of code instead:<\/P><PRE class=\"codeSample\">Redim arrLines(i)\n<\/PRE>\n<P>What would happen in that case? Well, in that case our array <I>would<\/I> be resized. However, any existing items in the array would be deleted, and we\u2019d be left with an empty array of size i.<\/P>\n<P>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\u2019ll 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\u2019s because the first item in an array is always given the index number 0.)<\/P>\n<P>So what happens once we have an array of size 0? Well, our next step is to use the <B>ReadLine<\/B> method to read the first line in the text file, then assign that value to item 0 in the array. That\u2019s what we do here:<\/P><PRE class=\"codeSample\">arrLines(i) = objFile.ReadLine\n<\/PRE>\n<P>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\u2019ll resize the array to a size of 1 (meaning the array can now hold 2 items), then we\u2019ll read the next line in the text file and assign <I>that<\/I> value to the second item in the array (the item with the index number 1). This process then continues until we\u2019ve 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 <B>Close<\/B> method to close the file C:\\Scripts\\Test.txt.<\/P>\n<P>So what does all this mean? This means that the array arrLines now contains the individual lines in the text file, lines that we\u2019ll assume look like this:<\/P><PRE class=\"codeSample\">E. This is line 5.\nD. This is line 4.\nC. This is line 3.\nB. This is line 2.\nA. This is line 1.\n<\/PRE>\n<P>In other words, arrLines is now the spitting image of the file C:\\Scripts\\Test.txt.<\/P>\n<P>At this point we\u2019re ready to rotate the text file. As it turns out, VBScript doesn\u2019t include a function for rotating a text file; however, VBScript <I>does<\/I> include a procedure for reading an array from the bottom to the top. That\u2019s the approach we\u2019re going to use to reverse the lines in the file.<\/P>\n<P>To that end, our next step is to reopen the file C:\\Scripts\\Test.txt, this time for writing:<\/P><PRE class=\"codeSample\">Set objFile = objFSO.OpenTextFile(&#8220;C:\\Scripts\\Test.txt&#8221;, ForWriting)\n<\/PRE>\n<P>As soon as the file has been reopened, we execute this block of code:<\/P><PRE class=\"codeSample\">For i = Ubound(arrLines) to LBound(arrLines) Step -1\n    objFile.WriteLine arrLines(i)\nNext\n<\/PRE>\n<P>What we\u2019re doing here is reading the array from the bottom to the top: we\u2019re starting with the <B>Ubound<\/B> item (the last item in the array) and then finishing with the <B>Lbound<\/B> 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 <B>Step -1<\/B> to ensure that our loop runs backwards: item 4, item 3, item 2, item 1, item 0.<\/P>\n<P>Inside the loop, we simply use the <B>WriteLine<\/B> 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\u2019ve 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.<\/P>\n<P>Like watch yet another edition of <I>Baseball Tonight<\/I> on ESPN.<\/P>\n<P>So what\u2019s the net effect of all this? <I>This<\/I> is the net effect:<\/P><PRE class=\"codeSample\">A. This is line 1.\nB. This is line 2.\nC. This is line 3.\nD. This is line 4.\nE. This is line 5.\n<\/PRE>\n<P>As you can see, we\u2019ve 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.<\/P>\n<P>There you have it, BJM. Incidentally, we know that you had another question about text files. But don\u2019t worry; we\u2019ll 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 <I>not<\/I> include the phrase \u201cSo the last will be first and the first will be last.\u201d Instead, the correct translation is actually \u201cSo the last will be first and the Scripting Guys will be last.\u201d Which, needless to say, is something we\u2019ve known for a long time. <\/P>\n<P>Or at least since last year\u2019s performance review.<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I \u201crotate\u201d 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.&#8212; BJM Hey, BJM. You know, when most people [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[3,4,14,5],"class_list":["post-64123","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-scripting-guy","tag-scripting-techniques","tag-text-files","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I \u201crotate\u201d 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.&#8212; BJM Hey, BJM. You know, when most people [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/64123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=64123"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/64123\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=64123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=64123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=64123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}