Java Alternatives to CFDIRECTORY and ConvertDate

On Tuesday I was having a discussion with a coworker and somehow it came up that he was having issues using cfdirectory on a rather large directory of log files. I pointed him to Mark Kruger's Java Based Directory List blog post which I had just read last week. He took a look and sent back the following snippet:

[More]

Related Blog Entries

Comments
Dan G. Switzer, II's Gravatar @Nathan:

Just a note, in your code you're calculating dates based on today's DST offset. In reality, you should be calculating the offsets based on the date the file was modified, not now.

For example, a file modified last Friday (Oct 27, 2006) would have had an offset of +4 for EDT. However, now the offset would be +5 for EDT. In your example, it would show the date modified being off by an hour.
# Posted By Dan G. Switzer, II | 11/3/06 9:59 AM
Nathan's Gravatar Thanks for that catch Dan. I've updated the code example above. I haven't tested it but I think it should work. If anyone sees any problems please let me know.
# Posted By Nathan | 11/3/06 11:24 AM
Dan G. Switzer, II's Gravatar @Nathan:

That didn't quite work, but this code does for me:

<cfset jTimeZone = createObject("java", "java.util.TimeZone") />
<cfset jGregorianCalendar = createObject("java","java.util.GregorianCalendar").init() />
<!---
<cfset jGregorianCalendar.setTimeZone(jTimeZone.getTimeZone("America/New_York")) />
--->

<cfset fileList = createObject("java","java.io.File").init(expandPath(".")).listFiles() />
<cfset qDir = queryNew("Name,DateLastModified") />
<cfloop from="1" to="#arrayLen(fileList)#" index="i">
   <cfset jGregorianCalendar.setTimeInMillis(fileList[i].lastModified()) />
   <!---// modify for daylight savings //--->
   <cfset jGregorianCalendar.add(jGregorianCalendar.MILLISECOND, jGregorianCalendar.get(jGregorianCalendar.DST_OFFSET)) />
   <cfset queryAddRow(qDir) />
   <cfset querySetCell(qDir, "Name", fileList[i].getName()) />
   <cfset querySetCell(qDir, "DateLastModified", jGregorianCalendar.getTime()) />
</cfloop>

<cfdump var="#qDir#">

NOTE: The commented out setTimeZone() call can be used to set a custom timezone (so for example, you wanted to show the time stamps in the user's timezone.)
# Posted By Dan G. Switzer, II | 11/3/06 2:28 PM
Nathan's Gravatar Hi Dan,

This DST stuff is confusing. I just tried all three methods on a directory of log files that which happen to write the current date/time they were written to disk in the file name. Here is a snapshot from a windows DIR command on the directory:

02/23/2006 05:14 PM 645 LOG-02-23-06-051408PM.txt
07/08/2005 12:43 PM 1,304 LOG-07-08-05-014248PM.txt

Notice that the time listed by the DIR command is one hour off for the second file, which was written during EDT.

Running the original snippet I had posted I get results which match the file name timestamp:

{ts '2006-02-23 17:14:10'} LOG-02-23-06-051408PM.txt
{ts '2005-07-08 13:43:50'} LOG-07-08-05-014248PM.txt

Your snippet and my current snippet give me the same results. The files written in EDT are off by one hour, but in the opposite direction of the windows DIR listing:

{ts '2006-02-23 17:14:10'} LOG-02-23-06-051408PM.txt
{ts '2005-07-08 14:43:50'} LOG-07-08-05-014248PM.txt

I'm going to have to take a look at this over the weekend and see if I can make heads or tails of it. Thanks for all the feedback.
# Posted By Nathan | 11/3/06 4:10 PM
Nathan's Gravatar I reverted the example above to what I originally posted. This snippet should work on Windows, but what time it returns for files written during daylight saving time will depend on what your settings are for "Automatically adjust clock for daylight saving changes." Please see the related entry for more details.
# Posted By Nathan | 11/8/06 8:39 PM
JayBigam's Gravatar I was asked about speeding up cfdirectory when used with cftree and put this together using the code from this page and CF_Absolute2Relative...

while it doesn't function exactly as you might want cftree to work it brings load times down from over 1 minutes to a few seconds. I think it makes quite a nice file browser


This code to speed up cfdirectory when used with<br>
cftree was written by Jay Bigam contains <br>
java object code from Nathan Mische<br>
http://www.mischefamily.com/<br>;
and<br>
CF_Absolute2Relative custom tag by Eric A. Gravel <br>
(freely available in the adobe CF tag exchange)<br>

Free for all use. Leave notices intact. No Warranty. Use at your own risk.<br>
Note: <br>
cftreeitem for directories should be modified to suit your url <br>
Your page must call itself and must have ?rootdir=#wholePath# appended<br>
I've used Courier for monspacing so the ....... vPad spacing works.<br>
If you don't like this remove the vPad code or set showDate = false<br>

<hr>


<cfoutput>
<cfparam name="url.rootDir" default="">
<cfparam name="MaxTop" default="">
<cfset ShowDate = true>



<cfset topLvl = "c:\inetpub\wwwroot\"><!--- set to whatever root you want. --->
<cfif url.rootdir eq "">
<cfset rootdir = "#topLvl#">
<cfset MaxTop = len(rootdir)>
<cfelse>
<cfset rootdir = "#topLvl#">
<cfset MaxTop = len(rootdir)>
<cfset rootdir = "#replace(url.rootDir,"?","")#">
</cfif>
<cfif len(url.rootdir) LT MaxTop><!--- requesting a dir above root so bail --->
<div style="width:50%;font-color:##0000CC;border:1px solid; background-color:##EEEEEE;padding:10px;Margin:auto;">
Top Level Reached
<a href="codesubmit.cfm?rootdir=#topLvl#">GO Back</a></div>
<cfelse>
<cfif showDate eq True>
<!--- date code optional --->
<cfset jGregorianCalendar = createObject("java","java.util.GregorianCalendar").init() />
<cfset jCalendar = createObject("java","java.util.Calendar") />
<cfset dstOffset = jGregorianCalendar.get(jCalendar.DST_OFFSET) />
<cfset zoneOffset = jGregorianCalendar.get(jCalendar.ZONE_OFFSET) />
<cfset offset = dstOffset + zoneOffset />
</cfif>

<cfset fileList = createObject("java","java.io.File").init("#rootdir#").listFiles() />
<cfset myDir = queryNew("Name,type,DateLastModified") />
<cfloop from="1" to="#arrayLen(fileList)#" index="i">
<cfset queryAddRow(myDir) />
<cfset querySetCell(myDir, "Name", fileList[i].getName()) />
<cfset querySetCell(myDir, "type", fileList[i].isDirectory()) />
<cfif showDate eq True>
<!--- date code optional --->
<cfset querySetCell(myDir, "DateLastModified", dateAdd('s', (fileList[i].lastModified() + offset)/1000, 'January 1 1970 00:00:00')) />
</cfif>
</cfloop>


<cfset wholePath = "#rootdir#" & myDir.Name>
<cfif len(wholePath) - len(rootDir) neq 0>
<cfset treeVal =Right(wholePath,len(wholePath) - len(rootDir))>
<cfset parVal = replace(wholePath,treeVal,'')>
<cfset vListlen = #listlen(parval,"\")# >
<cfset parentDir = #listdeleteat(parval,vListlen,"\")#>
<cfelse>
<!--- handle empty directories --->
<cfset vListlen = #listlen(wholepath,"\")# >
<cfset parentDir = #listdeleteat(wholepath,vListlen,"\")#>
</cfif>

<cfform>
<cftree name = "myDirTree"
format="flash"
font="courier"
fontsize="13"
highlighthref="yes"
height = "500"
width = "600"
hScroll = "no"
vScroll = "no"
enabled = "yes"
visible = "yes"
appendkey="no">
<cftreeitem value = "TOP" display=".."
parent = "" expand="false" img="folder"
href="codesubmit.cfm?rootdir=#parentDir#\">
<cfloop query="myDir">
<cfset wholePath = "#rootdir#\" & myDir.Name>
<cfset treeVal =Right(wholePath,len(wholePath) - len(rootDir))>
<cfset parVal = replace(wholePath,treeVal,'')>
<cfswitch expression="#myDir.Type#">
<cfcase value="YES">
<cftreeitem value = "#treeVal#" display="#myDir.Name#\"
parent = "#parVal#" expand="false"
href="codesubmit.cfm?rootdir=#wholePath#">
</cfcase>
<cfcase value="no">
<CF_Absolute2Relative
currentPath="#expandpath(rootdir)#"
destinationPath="#wholepath#"
>
<cfif showDate eq True>
<cfset vLeft= 50- #len(myDir.Name)#>
<cfset vPad = ".">
<cfloop from="0" index="Lcount" to ="#vLeft#">
<cfset vPad = vPad & ".">
</cfloop>
<cfset vDisplay = "#myDir.Name##vPad##dateformat(myDir.DateLastModified,"mm/dd/yyyy")#">
<cfelse>
<cfset vDisplay = "#myDir.Name#">
</cfif>

<cftreeitem value = "#treeVal#" display="#vDisplay#"
parent = "#parVal#" expand="false"
href="#CF_Absolute2Relative.Result#" target="blank">
</cfcase>
</cfswitch>

</cfloop>
</cftree>
</cfform>
</cfif>
</cfoutput>
# Posted By JayBigam | 2/2/07 5:30 PM
Jay's Gravatar I should point out that there is a security risk in the code above as it passes the absolute path in the url...you'd only want to use this internally without modifications to fix the issue.
# Posted By Jay | 2/2/07 5:44 PM
jay's Gravatar I've written parts to hide the absolute path
so instead of

codesubmit.cfm?fD=c:\inetpub\wwwroot\CFIDE\?
you get
codesubmit.cfm?fD=\\CFIDE\?


<!--- This code to speed up cfdirectory when used with<br>
cftree was written by Jay Bigam contains <br>
java object code from Nathan Mische<br>
http://www.mischefamily.com/<br>;
and<br>
CF_Absolute2Relative custom tag by Eric A. Gravel <br>
(freely available in the adobe CF tag exchange)<br>

Free for all use. Leave notices intact. No Warranty. Use at your own risk.<br>
Note: <br>
cftreeitem for directories should be modified to suit your url <br>
Your page must call itself and must have ?fD=#wholePath# appended<br>
I've used Courier for monspacing so the ....... vPad spacing works.<br>
If you don't like this remove the vPad code or set showDate = false<br>

<hr>
--->
<cfoutput>
<cfparam name="url.fD" default="">
<cfparam name="MaxTop" default="">
<cfset ShowDate = true>
<cfset topLvl = "c:\inetpub\wwwroot"><!--- set to whatever root you want. --->
<cfif url.fD eq "">
<cfset fD = "#topLvl#">
<cfelse>
<cfif replace(url.fd,"?","") eq topLvl>
<cfset fD = replace(url.fd,"?","")>
<cfelse>
<cfset fD = topLvl & url.fD>
<cfset fD = replace(fd,"?","", "ALL")>
</cfif>
</cfif>

<cfif showDate eq True>
<!--- date code optional --->
<cfset jGregorianCalendar = createObject("java","java.util.GregorianCalendar").init() />
<cfset jCalendar = createObject("java","java.util.Calendar") />
<cfset dstOffset = jGregorianCalendar.get(jCalendar.DST_OFFSET) />
<cfset zoneOffset = jGregorianCalendar.get(jCalendar.ZONE_OFFSET) />
<cfset offset = dstOffset + zoneOffset />
</cfif>

<cfset fileList = createObject("java","java.io.File").init("#fd#\").listFiles() />
<cfset myDir = queryNew("Name,type,DateLastModified") />
<cfloop from="1" to="#arrayLen(fileList)#" index="i">
<cfset queryAddRow(myDir) />
<cfset querySetCell(myDir, "Name", fileList[i].getName()) />
<cfset querySetCell(myDir, "type", fileList[i].isDirectory()) />
<cfif showDate eq True>
<!--- date code optional --->
<cfset querySetCell(myDir, "DateLastModified", dateAdd('s', (fileList[i].lastModified() + offset)/1000, 'January 1 1970 00:00:00')) />
</cfif>
</cfloop>


<cfset wholePath = "#fD#" & myDir.Name>
<cfif len(wholePath) - len(fD) neq 0>
<cfset treeVal =Right(wholePath,len(wholePath) - len(fD))>
<cfset parVal = replace(wholePath,treeVal,'')>
<cfset vListlen = #listlen(parval,"\")# >
<cfset parentDir = #listdeleteat(parval,vListlen,"\")#>

<cfset parentdir = replace(parentdir,topLvl,"")>

<cfelse>
<!--- handle empty low level directories --->
<cfset vListlen = #listlen(wholepath,"\")# >
<cfset parentDir = #listdeleteat(wholepath,vListlen,"\")#>
<cfset parentdir = replace(parentdir,topLvl,"")>
</cfif>



<cfform>
<cftree name = "myDirTree"
format="flash"
font="courier"
fontsize="13"
highlighthref="yes"
height = "500"
width = "600"
hScroll = "no"
vScroll = "no"
enabled = "yes"
visible = "yes"
appendkey="no">

<cfif #fD# neq #toplvl# & "\">
<!--- Hide .. upone if at topLvl --->
<cftreeitem value = "TOP" display=".."
parent = "" expand="false" img="folder"
href="codesubmit.cfm?fD=#parentDir#\">
</cfif>
<cfloop query="myDir">
<cfset wholePath = "#fD#\" & myDir.Name>
<cfset treeVal =Right(wholePath,len(wholePath) - len(fD))>
<cfset parVal = replace(wholePath,treeVal,'')>
<cfswitch expression="#myDir.Type#">


<cfcase value="YES">

<cfset urlpath = replace(wholePath,topLvl,"") & "\">

<cftreeitem value = "#treeVal#" display="#myDir.Name#\"
parent = "#parVal#" expand="false"
href="codesubmit.cfm?fD=#urlpath#">
</cfcase>
<cfcase value="no">
<CF_Absolute2Relative
currentPath="#expandpath(fD)#"
destinationPath="#wholepath#"
>
<cfif showDate eq True>
<cfset vLeft= 50- #len(myDir.Name)#>
<cfset vPad = ".">
<cfloop from="0" index="Lcount" to ="#vLeft#">
<cfset vPad = vPad & ".">
</cfloop>
<cfset vDisplay = "#myDir.Name##vPad##dateformat(myDir.DateLastModified,"mm/dd/yyyy")#">
<cfelse>
<cfset vDisplay = "#myDir.Name#">
</cfif>

<cftreeitem value = "#treeVal#" display="#vDisplay#"
parent = "#parVal#" expand="false"
href="#CF_Absolute2Relative.Result#" target="blank">
</cfcase>
</cfswitch>

</cfloop>
</cftree>
</cfform>
</cfoutput>
# Posted By jay | 2/2/07 7:30 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.