Java version of CFDIRECTORY

On November 6, 2007, in ColdFusion, by Anuj Gakhar

I had some free time today so I thought of writing some code to mimick CFDIRECTORY functionality using Java objects. As always, the idea of being able to call Java from within CF has always got me excited. I have seen a lot of code out there that uses JAVA to list files in a directory, however, I havent seen any code that returns all the attributes that CFDIRECTORY does. So this is what I decided to do today.

Here is the function I wrote Directory listing :-

Update : Dan Wilson kindly took the time to make some improvements to the function I wrote, it can be found here DirectoryListingNew

Here is how I used it :-

[xml]
<cfset args = structnew() />
<cfset args.pathToparse = "F:\install">
<cfset args.recurse = "true">
<cfset t = getTickCount() />
<cftimer label="timing" type="debug">
<cfset myquery2 = #DirectoryListing(argumentCollection=args)#>
</cftimer>[/xml]

On my machine this code takes 42ms to run. I think thats on the higher side as compared to the CFDIRECTORY tag in CF8 which takes only under 20ms for the same code. The only difference is that my function returns 2 new attributes, one of them is if the file is hidden or not and the second one is the path to the file.

This is a bit surprising for me as I thought the Java version would be faster but I think CF8 has made some major improvements in its file handling operations.

Any comments ?

Tagged with:  

18 Responses to Java version of CFDIRECTORY

  1. Marc Esher says:

    yours might be slower because of the extraneous createobject calls here:

    You’ve already defined your ioObject, so just define it with init() and reuse the ioObject for al those other File calls (isDirectory, isFile, isHidden, getPath, length).

    that should cut down on unneeded junk.

  2. Dan Wilson says:

    Hi Anju,
    Thank you for posting this. As an academic exercise, I have made changes to your file. In the below file, you will see two directory recursion tests. One, DirectorylistingAG, is your original function. The other, DirectorylistingDW is a modified version. Both are in a loop and the timing report will show which was faster.

    I removed 5 unnecessary createobject statements, 1 unused structNew call, several variable assignments, some conditional logic and made the recursion variable container ‘arguments.dirInfo1’ threadsafe. You will see this runs a lot faster now. To Test, you must change the value of pathToParse.

    Please let me know if you have any comments.

    Dan Wilson

  3. Dan Wilson says:

    I pasted the code in the comment. Your blog software wisely removes code. Thus, I have pasted it here for your comparison and comment.

    http://cfm.pastebin.com/f2051a413

  4. admin says:

    Hi Dan,

    You are right. Those 5 createObject calls were unnecessary. Silly me. Thanks for pointing that out. However, when I run this function, its still slower than the built in CFDIRECTORY.

    Looks like the only time its faster than the cf tag is when you dont access the extra attributes (size, datemodified, ishidden etc) …

    What do you think?

  5. admin says:

    Hi Dan, I’ve posted an update the my original post and included your improvements. Thanks.

  6. radek says:

    Anuj, it may be slower as you use query functions; you should try use java.sql.ResultSet instead of query funcs… Also you could try move the code to CFX tag.

  7. Anuj Gakhar says:

    Radek, I was actually trying to test this without throwing it all in a CFX tag.
    Do you think using java.sql.ResultSet will be faster than using queryaddrow and querysetcell() ?
    I was also thinking of using FileFilter/FileNameFilter classes for filtering the resultset.
    Will give it another visit when I get some free time…..
    thanks for the suggestions though…

  8. Radek says:

    I don’t think it will be faster as at the end i is compiled to byte code. I think your code works slower just because of compilin times. How did you test it?

  9. Anuj Gakhar says:

    I used CFTIMER to find out the processing times.

  10. Anuj,

    I’ve simplified this function as you can easily get an Array of file objects directly from the Files Class.

    http://cfm.pastebin.com/m7a4828ca

    However I didn’t do any performance metrics by comparing it with your earlier version. Let me know if you are able to find a way to apply FileFilter which is an interface.

    Thanks

  11. Anuj Gakhar says:

    Thanks Qasim, I am sure my first attempt was the same as what you’ve done but for some reason I was getting an error which is why I decided to do another CreateObject while inside the loop. But good to see that it works this way.
    Cheers!

  12. […] original post on this subject got some improvements and suggestions from different people. So I decided to put […]

  13. Anuj Gakhar says:

    Qasim, I tried using FileFilter but I think like you said, as its an Interface and not a class, its not possible to use it or atleast i couldnt do it…..may be someone else knows how to ?

  14. Marc Esher says:

    here’s a super simple filter i whipped up real quick a long time ago. you could drop it in your cf install’s classes directory then restart, then use MyFilter = createObject(“java”,”xxx.BeforeDateFilter”).

    there is also something on cflib.org for dynamic classloading if you didn’t want to deal with a server restart.

    package XXX;

    import java.io.File;
    import java.io.FileFilter;
    import java.util.Date;

    public class BeforeDateFilter implements FileFilter {
    long threshold;
    public BeforeDateFilter(Date thresholdDate){
    threshold = thresholdDate.getTime();
    }
    public boolean accept(File file) {
    return file.lastModified() < threshold;
    }
    }

  15. Anuj Gakhar says:

    Thanks Marc for this , that is interesting. I could put it all in a CFX and add a lot of other features but here in particular I was trying to do it via CreateObject() in CF itself. I assume that cant be done unless we create custon java classes like you did.

  16. Marc Esher says:

    Now, if you just wanted the ability to do the same filtering that’s in cfdirectory already, i.e. simple name-based file filtering, well, that’s pretty simple. potentially slow on a large directory, but you could do it one of two ways:

    1) do a simple query of query after you create your directory query
    2) simple IF statement in your loop

    However, you could still get around the problem by implementing your own FileFilter CFC, mimicing the java version (i.e. a single method…accept()) that takes file objects.

    you couldn’t pass it to the java listFiles call, but you could use it yourself in your own code, i.e.:

    if(arguments.FileFilter.accept(oFile){
    … do all your query new row stuff.
    }

    …. date stuff in java

    </cfcomponent

  17. Anuj Gakhar says:

    Thanks Marc. I think I was not being clear. I know we can do a CFC or a UDF or a CFX to do the same stuff as FileFilter in Java but this whole exercise was just to see if I could do it via creating java objects within CF code. But anyways, thanks for your suggestions. I think if its to be done without involving Coldfusion code, it should be done in a java class file like you said earlier…..

  18. […] is a stripped down version of Anuj Gakhar’s version of this function, his does recursion and returns even more data than cfdirectory […]

Leave a Reply to Marc Esher Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

© 2011 Anuj Gakhar
%d bloggers like this: