Java filhantering
Java är inte ett skriptspråk. Det är trevligt på många sätt, men ska man slänga ihop ett skript för att utföra diverse filoperationer så väljer man oftast inte Java. Det finns flera orsaker, ett av dem är knölig filhantering. För att öppna och skriva i en fil tvingas man till något liknande detta :
try{ FileWriter fstream = new FileWriter("out.txt"); BufferedWriter out = new BufferedWriter(fstream); out.write("Hello"); out.close(); }catch (Exception e){ System.err.println("Error: " + e.getMessage());}
Vilket är väldigt mycket krångligare än, säg…
echo Hello > out.txt
Det är här Ant kommer in. Ant är väldigt flexibelt och användbart verktyg för att använda Java på ett skriptbaserat sätt. Genom att använda ant-moduler, tasks kan man sätta ihop ganska avancerade skriptningar. Man kan även skriva egna tasks, vilket jag kommer att gå igenom här. För att skriva en task måste man extend:a Task. Vill man sedan ha en viss variabel, t ex en fil, behöver man bara deklarera dess set-metod. Själva jobbet utförs i execute(), som man override:ar
import java.io.File; import org.apache.tools.ant.*; public class HelloWorld extends Task { protected File file; protected String bar = "default"; public void setFile(File file){ this.file = file;} public void setFoo(String foo){ this.bar = foo;} public final void execute() throws BuildException{ if(file == null ) throw new BuildException("You must specify a file"); System.out.println("File selected : "+file); System.out.println("Foo : "+bar);}}
Ovanstående kommer att skapa en task som man kallar på följande vis :
<taskdef classname="se.swende.anttools.HelloWorld" name="hello" classpath="jar/antutils.jar"/><target name="test"><hello file="/etc/hosts" foo="goodbye cruel world"/></target>
Vilket ger följande output när man kör den :
test: [hello] File selected : /etc/hosts [hello] Foo : goodbye cruel world
Det blir mer intressant när man vill arbeta med hela filstrukturer och samlingar av filer. Naturligtvis har Ant bra stöd för detta : filesets. Vill man arbeta med filesets tar man helt enkelt emot dem i sin task :
/*** Adds files to operate on* @param fileset*/ public void addFileset(FileSet fileset) { filesets.add(fileset);}
Man opererar på sina filesets på följande vis :
for (FileSet fs: filesets) { DirectoryScanner ds = fs.getDirectoryScanner(getProject()); String[] includedFiles = ds.getIncludedFiles(); File base = ds.getBasedir(); for(int i=0; i<includedFiles.length; i++) { String fileName = includedFiles[i]; File inFile =new File(base,fileName); doJob(inFile,base); //The actual work on the file}}
Ur ant-perspektiv ser använder man filesets på liknande maner :
<fileset dir="./resources"><!-- All project files, except hidden and cvs-files --><exclude name="**/.*" /><exclude name="**/CVS/*" /></fileset>
För att förenkla för sig ytterligare kan man abstrahera bort detta till en basklass som man sedan ärver in i sina olika tasks. Nedan följer en implementation av en abstrakt basklass som jag själv brukar använda som basklass ifall jag vill operera på filer via ant.