Archive for the 'java' Category

01
Nov
09

using java for common scripting tasks:walking directories & processing files


I’m a fan of scripting languages. If you read some of the stuff I wrote, you may already know that ( if not, check the URL of this website ). You can solve many/all tasks using a scripting language, but, sometimes you’d like to benefit from the speed that a typed language can give you. I think the most frequent task one has to do is process files. But, to do that, first you have to find them, scan directories, filter them, store them in some collection, and only then you can start processing them.

One of the downsides is that usually, code that would take several lines in a language like let’s say Ruby, becomes pretty verbose in Java. Here’s a sample:


Find.find(folder) do |file|
   puts file if File.directory?(file)
end

The code listed above will print all the directories ( and subdirectories ) contained in the folder parameter. 3 lines! Imagine how many you’d have to write in Java. You don’t have a built-in directory walker, so you’d need to roll your own methods/class.
Then, you would want your walker to be usable in all the tasks you may encounter, so that you don’t have to rewrite the whole thing when you need to enumerate all the zip archives inside a folder, or mp3’s. Usually, writing methods that accept callbacks is a great practice. In fact, the code written above illustrates that concept exactly. The stuff contained between the do and end is a block, Ruby’s way of implementing callbacks.
In Java, we don’t have first class functions, but we can achieve kinda the same thing by using interfaces. How does the following Java code look like:


File directory = new File("c:/");
FileWalker.walkDirectory(directory, new Callback<File>() {
        public void action(File t) {
             if(t.isDirectory())
                 System.out.println(t);
        }
});

I’d say it’s not that bad! You can live with that, right? What if you’d like to add them to a list and process them later? The following snippet shows you how to do that:


File directory = new File("c:/");
final ArrayList<File> results = new ArrayList<File>();
FileWalker.walkDirectory(directory, new Callback<File>() {
     public void action(File t) {
        if(t.isDirectory())
           results.add(t);
     }
});
for(File result : results)  {
    System.out.println(result);
}

I don’t know about you, but most ( if not all ) directory walking and file searching stuff I do, involves getting a list of files first, and processing them later. So that I don’t have to write all that code when I need to do this, I created a selectFiles method which does exactly that: return a list of files matching a certain condition. Here’s an example of it’s usage:


File directory = new File("c:/");
ArrayList>File> results = FileWalker.selectFiles(directory, new Selector>File>(){
    public boolean accept(File t) {
       return t.isDirectory();
    }
});
for(File result : results)
{
    System.out.println(result);
}

It doesn’t save you that many keystrokes, but it saves you from declaring a list, and doing everything inside a callback. Think of that Selector as a Filter. Here’s the code behind all the classes showed here:
The Selector interface:


public interface Selector<T> {
    public boolean accept(T t);
}

The Callback interface:


public interface Callback<T> {
    public void action(T t);
}

And the FileWalker class:


public class FileWalker {

    /**
     * select all files from a folder, matching a condition
     * @param root folder
     * @param selector selector object
     * @return list of files matching criteria
     */
    public static ArrayList<File> selectFiles(final File root,final Selector<File> selector)
    {
        final ArrayList<File> files = new ArrayList<File>();
        FileWalker.walkDirectory(root, new Callback()
        {

            public void action(File t) {
                boolean add = true;
                if(selector != null)
                {
                    add = selector.accept(t);
                }
                if(add) { files.add(t); }
            }

        });
        return files;
    }

    /**
     * walk a directory recursively
     * @param root folder
     * @param callback callback object
     */
    public static void walkDirectory(File root,Callback<File> callback)
    {
        File kids[] = root.listFiles();
        callback.action(root);
        if(kids != null)
        {
            for(File kid : kids)
            {
                walkDirectory(kid,callback);
            }
        }
    }

}

Whenever I get the chance, I do this sort of stuff in Ruby/Groovy/Python. I prefer development speed over execution speed. But, sometimes, you just can’t afford going into a dynamic language, and using plain Java for this sort of tasks looks like something you can cope with. Hang in there! :)

19
Oct
09

overloading the in operator in groovy


You can do stuff like this in Groovy:


def a = [1,2,3,4]
println 4 in a

and it will print true. I thought it would be cool to be able to do that for custom classes, but I didn’t know how to do it, so I asked on stackoverflow: question.
After I haven’t received an answer, I posted the same question on the groovy mailing list : nabble thread. Guillaume Laforge provided the solution: you need to override isCase.
Here’s something that works:


class Whatever {
   def container = []
   def addItem(item) {
      container << item
   }
   def isCase(o) {
      return o in container
   }
}

a = new Whatever()
a.addItem("one")
a.addItem("two")
println "two" in a

Really nice!

28
Sep
09

recursive directory walker using jython


Several months ago I wrote a post related to creating a recursive directory walker in Python. We did not make use of os.walk. While playing with Jython I thought it would be nice to write an equivalent. Here’s what I have :


from java.io import File
import sys

class FileWalker(object):
	def walk(dir,cbf):
	    files = dir.listFiles()
	    for file in files:
	        cbf(file)
	        if file.isDirectory():
	            FileWalker.walk(file,cbf)
	walk = staticmethod(walk)

def list_file(file):
    print "saw %s" % file

if __name__ == "__main__":
    FileWalker.walk(File(sys.argv[1]),list_file)

I think the code is pretty straight-forward. If you’re familiar with Java even a little bit, I’m sure you can understand what’ s going on in here. You should know that the callback function isn’t receiving a string as it’s parameter ( as the first version of the walker did ) . This one receives a Java File object, which means you have access to all the methods present in the File class.

05
Aug
09

java chdir


If you need to use a chdir call in Java, here’s how chdir could be implemented :


public void chdir(String directory) {
  System.setProperty("user.dir",directory);
}

UPDATE:it seems chdir doesn’t work in Java. This tells you why.

20
Jul
09

unclosed files in Java


Small tip: if you don’t close your opened files, you may not be able to delete them using File.delete. If you find you’re in that situation, try to do a System.gc() before the delete call. Sometimes it helps.

If calling the garbage collector doesn’t work, you’ll have to close them from your code.

29
Jun
09

my new favourite language


Even though I’ve been programming in Groovy only for a couple of days, I really like it. It’s quickly becoming my new favorite language.

28
Jun
09

how to run your java class’s main method from jruby


Last night I wrote a Java class that performs a checkout from a SVN repository. I was able to integrate it with Groovy really fast, and was wondering how fast I could get it going with JRuby. I started to do some research on google, I downloaded the JRuby binary from http://dist.codehaus.org/jruby/, and I fired up jirb to do some quick testing.
Before I get to the JRuby part, let me add a little bit of information about the class I wanted to run: the only method I was interested to run was main, because most of the information was hardcoded in it.

So, I imported Java’s String class, hoping to build an array I could pass to main.


java_import "java.lang.String" do |package,classname|
   "J#{classname}"
end

This imports Java’s String class under the name JString, because Ruby has a String class as well. To create a JString object, you use Ruby’s regular object creation syntax :


JString.new("whatever")

Ok, so after I imported the java.lang.String class, I created an array of them:


args = [JString.new("argument"),JString.new("otherArgument")]

And I passed it to the class’s main method :


require "java"

java_import "java.lang.String" do |pk,nm|
  "J#{nm}"
end

java_import "SCli"
args = [JString.new("first_arg"),JString.new("second_arg")]
SCli.main(args)

Notice I imported the SCli class as well. That is my Java class. In order for the import to work, you should place the class in the CLASSPATH variable, or add the class file to your JRuby project’s lib folder and add that folder to the CLASSPATH. Also, if your class is inside a package, you should add that to the java_import line. Mine wasn’t in one.

Running this script gave me the following error :

main.rb:9: for method main expected [#<Java::JavaClass:0x9d5793>]; got: [org.jruby.RubyArray]; error: argument type mismatch (TypeError)

I was kind of hoping the array would pass for a Java array :) . So, I started to search after this error message, and I got to the Calling Java from JRuby page. After a little bit of reading, I got it to work using the following script :


require "java"

java_import "SCli"
args = ["arg1","arg2"].to_java(:string)
SCli.main(args)

Nice,right?

20
Jun
09

aribaweb is an interesting framework


Randomly browsing stackoverflow ( I do that sometimes ), I found this question. I visited aribaweb’s page and I was very impressed with the Building a guestbook screencast.

When I have some free time, I’ll check it out.