Using ColdFusion 9's new FileSeek

Another new feature in ColdFusion 9 (and unfortunately not documented) is the new FileSeek ability. The basic idea of seeking in a file is jumping to an arbitrary position. This could be useful for a variety of reasons. For example, certain binary files may store information at the end of a file. Another example is getting the end of a long log file. I blogged about this back in April using Java via ColdFusion. ColdFusion 9 makes this somewhat easier with the addition of FileSeek. As I said though, this is currently undocumented. Thanks to Rupesh for sending me the basics which I’ll cut and paste right here:

FileOpen(path, mode, charset, seekable) - If seekable is true, you will be able to call fileSeek() and fileSkipBytes() . returns file handle FileSeek(fileObj, pos) FileSkipBytes(fileObject, noOfBytesToSkip)

Seems easy enough, right? Here is an example that mimics the Java code from my previous example. First, define the file and create a file object for it:

<cfset theFile = "/Applications/ColdFusion9/logs/server.log">

<cfset fileOb = fileOpen(theFile, “read”, “utf-8”, true)> </code>

Notice the new seekable argument there. Next, let’s define a few variables:

<!--- number of lines ---> <cfset total = 10>

<cfset line = ““> </code>

Total is pretty obvious. The line variable will actually store my characters as I read it in. I should have called it buffer, or buffy, or maybe pinkpajamas.

<!--- go to the end of the file ---> <cfset pos = fileOb.size-1> <cfset fileSeek(fileOb, pos)>

The next block of code uses the fileSeek. Notice that I define my position as the size of the file minus one. This will let me read a character in the code coming up.

<!--- go backwards until we get 10 chr(10) ---> <cfloop condition="listLen(line,chr(10)) lte total && pos gt 0"> <cfset c = fileRead(fileOb, 1)> <cfset line &= c> <cfset pos--> <cfif pos gt 0> <cfset fileSeek(fileOb, pos)> </cfif> </cfloop>

So this CFML code is pretty much the exact same as the Java-based code. Get a character. Add it to the line. Move backwards, and loop until we hit the beginning of the file or 10 lines. ColdFusion will do this for us, but it is a good idea to close the file:

<!--- close the file ---> <cfset fileClose(fileOb)>

Now we need to manipulate the string a bit. It is both reversed and has an additional character in it:

<!--- will always have one additional char ---> <cfset line = trim(mid(line, 1, len(line)-1))>

<!— reverse it —> <cfset line = reverse(line)> </code>

And that’s it! We now have a string with 10 lines from the end of the file. The complete template may be found below.

<cfset theFile = "/Applications/ColdFusion9/logs/server.log">

<cfset fileOb = fileOpen(theFile, “read”, “utf-8”, true)>

<!— number of lines —> <cfset total = 10>

<cfset line = ““>

<!— go to the end of the file —> <cfset pos = fileOb.size-1> <cfset fileSeek(fileOb, pos)>

<!— go backwards until we get 10 chr(10) —> <cfloop condition=”listLen(line,chr(10)) lte total && pos gt 0”> <cfset c = fileRead(fileOb, 1)> <cfset line &= c> <cfset pos–> <cfif pos gt 0> <cfset fileSeek(fileOb, pos)> </cfif> </cfloop>

<!— close the file —> <cfset fileClose(fileOb)>

<!— will always have one additional char —> <cfset line = trim(mid(line, 1, len(line)-1))>

<!— reverse it —> <cfset line = reverse(line)>

<cfoutput> <pre> #line# </pre> </cfoutput> </code>

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate. He focuses on JavaScript, serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Comments