You are hereMonthly Archive / juni 2009
juni 2009
Kopiera filer/mappar i Java
Att läsa och skriva filer i Java är inte särskillt svårt. Men hur gör man för att kopiera en fil eller en mapp? Det finns ingen native funktion som hanterar detta. Inte vad jag vet om i alla fall.
Det man får göra är helt enkelt att man öppnar källfilen som en ström och sedan skriver till en annan ström som är destinationsfilen. För att underlätta hanteringen av detta skrev jag ihop en liten klass som gjorde detta.
Enjoy!
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * DiskUtility is a bunch of smart functions to perform disk-operations. */ public class DiskUtility { /** * Copies a file or folder from one location to another * @param srcPath The source path to file/folder * @param dstPath The destination path to file/folder * @throws IOException */ public static void copy(File srcPath, File dstPath) throws IOException{ if (srcPath.isDirectory()) { // If destination path doesn't exist, create it if (!dstPath.exists()) { if(!dstPath.mkdir()) { throw new IOException("Could not create direcotry."); } } // List all files in the directory String files[] = srcPath.list(); // Loop through all files and copy them for(int i = 0; i < files.length; i++) { File source = new File(srcPath, files[i]); File destination = new File(dstPath, files[i]); copy(source, destination); } } else { // If source path does not exist if(!srcPath.exists()){ throw new FileNotFoundException("File or directory does not exist."); } else { InputStream in = new FileInputStream(srcPath); OutputStream out = new FileOutputStream(dstPath); // Transfer bytes from in to out byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } in.close(); out.close(); } } } }
Unix timestamp till Java date
Idag stötte jag på ett problem som jag hade svårt att hitta en lösning på. Därför tänkte jag dela med mig av detta.
Hur konverterar jag en Unix timestamp skapat via PHP's time() till Java's Date?
En UNIX timestamp är antalet sekunder som passerat sedan midnatt den 1:a januari 1970, vilket används bredd inom datavärlden. Utan att titta närmare på API:t för Java's date objekt så slängde jag bara med timestampen som en long i konstruktorn för Date.
Till min förvåning så blev parsningen av datumet helt fel. Efter lite felsökning och läsning i Java's API ( http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Date.html ) så kunde jag utläsa att att Date tar en long med antalet millisekunder som argument, och inte sekunder. Efter en enkel multiplikation så gjorde jag ett nytt försök.
Denna gång blev det bättre.
Long timestamp = 1245048815L; Date date = new Date(timestamp * 1000); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); System.out.println(df.format(date));
Hibernate, Spring och lazy loading
Hibernate erbjuder både lazy och non-lazy loading av objekt instansiering. Non-lazy loading innebär att man hämtar alla objekt och dess relaterade objekt vid load time. Detta kan leda till att hundratals objekt skapas när man ska hämta en enda entitet. Lazy loading betyder däremot att man bara hämtar ett objekts relaterade objekt när man accessar dem. Detta är helt transparant gentemot användaren och minimerar antalet requests gentemot databasen, vilket resulterar i stora prestandafördelar.
Det finns dock en nackdel. Använder man sig av lazy loading måste man se till att man håller sin session öppen så länge ojektet används. Detta leder till problem när man försöker abstrahera persistens lagret mha av Data Access Objekt mönstret. För att göra detta ordentligt så ska all databas logik, såsom öppna och stänga sessioner, inte göras i applikationslagret. Normalt implementeras detta bakom DAO implementationen, gömt från användaren. Man skulle kunna skippa hela DAO mönstret och inkludera detta direkt i applikationslagret. Detta fungerar endast för små applikationer, men inte för större.
Använder man sig av Spring tillsammans med Hibernate så finns det en redan implementerad och enkel lösning. Använder man sig av en web applikation så erbjder Spring både av en interceptor (OpenSessionInViewInterceptor) och ett filter (OpenSessionInViewFilter). Vilken man använder sig av spelar ingen roll. Skillnaden är att interceptern körs i spring containern och konfigureras iweb application context, medan filtret framför Spring och konfigureras i web.xml. Båda öppnar en hibernate session vid en request och binder den till den aktuella tråden där den sedan kan användas transparant av DAO implementationen. Sessionen hålls öppen för viewn så lazy loading kan utföras. Den stängs sedan när all view logik är klar antingen via filtrets doFilter metod eller interceptorns postHandle metod.
Interceptor konfiguration
Filter konfiguration
... ... hibernateFilter org.springframework.orm.hibernate.support.OpenSessionInViewFilter ... hibernateFilter *.spring
Singleton klasser
Jag får ofta frågan om hur en singelton klass implementeras. En singleton klass är en klass som det endast kan finnas en instans av har ett globalt sätt att accessa den.
public class Singleton { private static Singleton instance; // Other useful instance variables here private Singleton() {} public static Singleton getInstance() { if(instance==null) { instance = new Singleton(); } return instance; } // Other useful methods here }
Vad händer här? Först deklarerar vi en statisk variabel som är hållare till vår instans i singleton klassen. Konstruktorn görs privat, för det är endast vår klass som ska kunna skapa instansen. Metoden getInstance() möjliggör ett sätt att skapa vår enda instans, samt returnera den. En singleton klass är som vilken annan klass, så den kan självklart ha fler variablar och metoder.