ColdFusion 8 adds a few cool new tricks to the venerable CFLOOP tag. This includes looping over files and and arrays. Let's take a look at file looping first.
You have two ways to loop over a file. In both cases however you simply add the new file attribute to the cfloop tag. Consider this first example:
<cfset filename = expandPath("./imageuploadform.cfm")>
<cfloop file="#filename#" index="line">
<cfoutput>#htmlEditFormat(line)#<br /></cfoutput>
</cfloop>
I supply a filename, and the index attribute will automatically be set to one line of the file. Note that I don't need to worry about file decimeters. ColdFusion handles that for me. Another very important tip - ColdFusion reads the file line by line. If you run this over a 200 meg file, ColdFusion doesn't have to read the entire file in - it just reads the portion it needs to. This is much better than using cffile to read the file and list functions to loop.
Another interesting variation on this is the characters attribute. The characters attribute lets you specify how many characters to read from the file at a time. If you have a file with a particular format, this can make it easier to get the data you need. Con sider this version:
<cfloop file="#filename#" index="snip" characters="10">
<cfoutput>#htmlEditFormat(snip)#<br /></cfoutput>
</cfloop>
Unlike the first example - this one will display 10 characters from the file each iteration, until the file is completely read.
One thing you can't do - and I'm hoping they add this to a future release - is just ahead in a file. Imagine that 200 meg file I mentioned earlier. Now imagine it is a log file and you want to show the last 100 lines. It would be nice if we could "seek" into the file before looping.
So lastly - cfloop also adds an array attribute. I believe this has already been mentioned on my blog. Basically it lets you loop over an array:
<cfset foo = [1,2,3,4,5,6,7,8,0]>
<cfloop array="#foo#" index="x">
<cfoutput>#x#<br></cfoutput>
</cfloop>
All handy stuff, and that frankly is one of the reasons I love ColdFusion 8. So many of the new features are just so darn handy.
Archived Comments
So, in theory, SpoolMail could be adjusted to loop over the .cfmail file, set multiple variables for the various items (server, from, to, subject, body, etc.), and functions could be written in where anything could be changed prior to re-sending the message. For instance, correcting the 'to' address of a message, resetting the 'server' attribute in all messages prior to re-sending (useful if messages have become trapped in the spool due to a server failure and changeover), etc. The only thing missing is a method to crop each 'line' of the body to set a bodyArray to re-build each 'body' line...
Good post Ray! That stuff about file looping is awesome!
Cutter - I'm not quite sure that would be a good use. In SpoolMail's case, every line is different, based on what is in front of the line. I'm not quite sure I'd use it for this. Not sure anyway.
To a degree I don't think it matters right now. I just tried to install it on CF 8, following the install instructions, and it doesn't create the new menu option in the administrator. Maybe something different in how the CFIDE is constructed.
Is every line different? As you loop each line of the file you could look for "from:", "to:", "server:", starting from position 1 of the line. Or, you could automatically split each line at the first ":", setting a variable of the name of the first array element to the value of the second, or concatenating a variable if it's name already exists.....
Cutter - are you 100% sure? There was a bug earlier for the menu thing. It is fixed in my copy of CF8. If you don't see this, please file a bug with Adobe. But I'm 99% sure this is fixed.
What about multidimensional array. A one dimension array.. is no more different then a list.
You're right, having startIndex and endIndex work with these would be very useful.
Ray,
In CF8, what if I need to know which element of the array I'm on?
given: arrFilter[1] has three data items [dog,cat,bird]
<cfloop array="#arrFilter#" index="i">
#i# -
</cfloop>
dog - cat - bird -
But, I need to know which position of the array I'm at. How?
Jim
Then you use the old format, from 1 to array len. :)
You could also create your own counter var. Struct loops aren't always in order, but array loops are. Just set a var, then increment it inside your loop.