pátek 24. října 2008

Nové API pro práci (nejen) se soubory

Tak už jsem si myslel, že nám tu zůstane java.io.File na věky věků jako jediná abstrakce pro práci se souborovým systémem v Jave. Dlužno dodat trochu nepovedená abstrakce. Naštěstí za hlavu se nechytali, jenom všichni jenž byli nuceni toto API používat a tak nám vzniklo JSR 203 More New I/O APIs for the Java Platform ("NIO.2"), které bude součástí JDK 7. Toto nové API řeší celkem tři oblasti, a to kromě lepšího rozhraní pro práci s souborovým systémem i asynchronní IO a doplnění socket-channel funkcionality.

Centrálními třídami nového package java.nio.file a java.nio.file.attribute budou FileSystem jako základní abstrakce pro práci se souborovým systémem a Path vyjadřující systémově závislou cestu k adresáři/souboru a BasicFileAttributes představující metadata (velikost, ACL, čas poslední změny atd.) k danému resourcu. Na další třídy se můžete podívat v javadocu.

Kromě toho, že celé API je rozšiřitelné, takže si budeme moci napsat například vlastní FileSystem implementaci nad naším obskurním souborovým systémem reprezentovaným REST interfacem, nás bude zajímat práce se samotnými soubory a to konkrétně jejich kopírování/přesouvání či zápis/čtení do souboru.

import static java.nio.file.StandardCopyOption.*;

Path source = Path.get("C:\\My Documents\\Stuff.odp");
Path target = Path.get("D:\\Backup\\MyStuff.odp");
source.copyTo(target);
source.copyTo(target, REPLACE_EXISTING, COPY_ATTRIBUTES);

Všechny operace, které nové IO API definuje a mohou končit IOException, tak opravdu touto výjimkou končí. Díky tomu nejsou výjimečné stavy řešeny boolean návratovou hodnotou jako tomu je ve starém IO API viz například metoda renameTo. Nové API by mělo být v tomto směru konzistentní. Díky tomu, že nové API počítá i s metadaty k souborům/adresářům je možné celkem rozumě zacházet například se symbolickými linky.

Funkčnost, která mi přišla zajímavá představuje podpora notifikací a asynchronního IO. Vznikla třída WatchService, která umožňuje sledovat danou entitu na typy události - čtení, smazání a nebo změnu. díku tomu bude jednoduché reagovat například na změnu souboru.

WatchService watcher = FileSystems.getDefault().newWatchService();
Set<StandardWatchEventType> events =
EnumSet.of(ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
WatchKey key = dir.register(watcher, events);
for (;;) {
    // wait for key to be signalled
    key = watcher.take();
    // process events
    for (WatchEvent<?> ev: key.pollEvents()) {
        if (event.getType() == ENTRY_MODIFY) {
            //do something
        }
    }
    // reset key
    key.reset();
}

Asynchronní podpora nám umožňuje provádět určité operace, např. kopírování souboru, asynchronním způsobem za použít abstrakcí jako java.util.concurrent.Future a nebo za použití callbacku. Ale co bych vám povídal, materiálu k dispozici je přehršel.