NIO 2

Post on 05-Dec-2014

2.077 views 1 download

description

 

Transcript of NIO 2

2

Architecte logiciel Java/.Net

Auteur de deux didacticiels diffusés sous la licence GNU FDL : http://www.jmdoudoux.fr Développons en Java (2330 pages) Développons en Java avec Eclipse (600 pages)

Rédacteur pour developpez.com,

Membre du Yajug et du CA du Lorraine Jug

Qui suis-je ?

NIO2

FileSystem API

Lectures/écritures : API mises à jour

Canaux asynchrones (Asynchronous I/0)

Conclusion

3

Plan

4

NIO 2

5

Le manque d’opérations basiques (copie, déplacement de fichiers, …)

Ne fonctionne pas de la même manière sur toutes les plateformes

Support limité des liens symboliques et des méta-données

Les défauts de java.io

6

Encapsule le chemin et les opérations

Gestion de certaines erreurs : certaines méthodes renvoient un booléen sans lever d’exceptions (delete() par exemple)

Manque de performance de certaines méthodes notamment listFiles()

=> besoin d’une nouvelle API

Les défauts de la classe File

7

Spécification JSR 203

JSR 203 : http://www.jcp.org/en/jsr/detail?id=203

8

NIO 2

JSR 203 : ajout de nouvelles API au package NIO

Accès et manipulation du système de fichiers

Mise à jour de l’API existante

Canaux asynchrones (asynchronous channels)

Inclus dans Java SE 7

9

FileSystem API

10

FileSystem API

API moderne, complète et extensible

Package java.nio.file et sous packages

Accès et gestion des systèmes de fichiers (fichiers, répertoires, liens symboliques)

Support des méta-datas

Parcours des répertoires

Extensible pour fournir sa propre implémentation (sous classe de FileSystem)

11

L’API FileSystem

12

Les principaux nouveaux concepts

Path : encapsule un chemin dans le système de fichiers

Files : méthodes statiques pour des opérations sur les fichiers et les répertoires

FileSystem : encapsule un système de fichiers, fabrique d’objets pour y accéder

FileSystems : fabrique d’instances de FileSystem

FileStore : encapsule le système de stockage sous jacent

13

L’interface Path

14

L’interface Path

Encapsule tout ou partie du chemin d’un élément du système de fichiers

Dépendant du système de fichier

Le chemin encapsulé existe ou non

Immuable

Chemin encapsulé absolu ou relatif

Pas de gestion des extensions des fichiers

Implémente Iterable et Comparable

15

L’interface Path

Création à partir d’un String, URI ou java.io.File

La classe helper Paths Paths.get("monfichier.txt");

Paths.get("jm/AppData/Local/Temp/monfichier.txt");

Paths.get("C:/Users/jm/AppData/Local/Temp/monfichier.txt");

Paths.get("C:\\Users\\jm\\AppData\\Local\\Temp\\monfichier.t

xt");

Paths.get(URI.create("file:///C:/Users/jm/AppData/Local/Temp

/monfichier.txt"));

Paths.get(System.getProperty("java.io.tmpdir"),

"monfichier.txt");

FileSystems.getDefault().getPath("logs", "access.log");

16

L’interface Path : gérer les éléments du chemin

Nombreuses méthodes pour gérer les éléments hiérarchiques du chemin

Path getFileName() : nom du dernier élément

Path getParent() : chemin parent ou null

Path getRoot() : racine du chemin ou null

Path subPath(int, int) : sous chemin

Path getName(int) : élément à l’index fourni

int getNameCount() : nombre d’éléments dans le chemin

17

L’interface Path : exemple

toString() = C:\Users\jm\AppData\Local\Temp\monfichier.txt

getFileName() = monfichier.txt

getRoot() = C:\

getName(0) = Users

getNameCount() = 6

getParent() = C:\Users\jm\AppData\Local\Temp

subpath(0,3) = Users\jm\AppData

toString() = jm\AppData\Local\Temp\monfichier.txt

getFileName() = monfichier.txt

getRoot() = null

getName(0) = jm

getNameCount() = 5

getParent() = jm\AppData\Local\Temp

subpath(0,3) = jm\AppData\Local

18

L’interface Path : manipuler des chemins

Plusieurs méthodes pour manipuler les chemins

Path normalize() : supprime les éléments redondants (par exemple . et ..), purement syntaxique

Path resolve(Path) : combiner deux chemins

Path relativize(Path) : chemin relatif entre le chemin et celui fournit

19

L’interface Path : manipuler des chemins

path = Paths.get("C:/Users/admin/

./../jm/AppData/Local/Temp/./monfichier.txt");

System.out.println("normalize() = " + path.normalize());

normalize() = C:\USers\jm\AppData\Local\Temp\monfichier.txt

Path path = Paths.get("C:/Users/jm/AppData/Local/");

Path nouveauPath = path.resolve("Temp/monfichier.txt");

System.out.println(nouveauPath);

nouveauPath = path.resolve("C:/Temp");

System.out.println(nouveauPath);

C:\Users\jm\AppData\Local\Temp\monfichier.txt

C:\Temp

20

L’interface Path : comparer des chemins

Plusieurs méthodes pour comparer les chemins

int compareTo(Path other) Compare le chemin avec celui fourni en paramètre

boolean endsWith(Path other) boolean endsWith(String other) Compare la fin du chemin avec celui fourni

boolean startsWith(Path other) boolean startsWith(String other) Compare le début du chemin avec celui fourni

21

L’interface Path : convertir des chemins

Plusieurs méthodes pour convertir les chemins

Path toAbsolutePath() : retourner le chemin absolu du chemin

Path toRealPath(LinkOption…) : retourner le chemin physique du chemin notamment en résolvant les liens symboliques selon les options fournies. Exception si le fichier n’existe pas ou s’il ne peut pas être accédé

22

L’interface Path : intégration dans l’existant

Path File.toPath()

File Path.toFile()

URI Path.toUri() : retourner le chemin sous la forme d’une URI

23

Glob

Pattern à appliquer sur un élément du système de fichiers

Sous ensemble des expressions régulières : * ** ? [] {} \

*.java éléments dont le nom fini par .java

??? éléments dont le nom est composé de trois alphanumériques

A*.java éléments dont le nom commence par un a et se termine par .java

*[0-9]* éléments dont le nom contient au moins un chiffre

*.{htm,html} éléments dont le nom se termine par htm ou html

24

Glob : exemple

Path file1 = Paths.get("c:/test.java");

Path file2 = Paths.get("c:/test.txt");

PathMatcher matcher =

FileSystems.getDefault().getPathMatcher("glob:*.{java,cla

ss}");

matcher.matches(file1);

matcher.matches(file2);

25

La manipulation des fichiers et des répertoires

26

La classe Files

Ensemble de méthodes statiques

Création : createDirectory(), createFile(), createLink(), createSymbolicLink(), createTempFile(), createTempDirectory(), …

Manipulation : delete(), move(), copy(), …

Type d’élément : isRegularFile(), isDirectory(),…

Méta-Datas et permissions : getAttributes(), getPosixFilePermissions(), isReadable(), isWriteable(), size(), getFileAttributeView(), …

27

Exemple : supprimer un fichier (1/2)

Path path = Paths.get("C:/java/test/monfichier_copie.txt");

try {

Files.delete(path);

} catch (NoSuchFileException nsfee) {

// traitement en cas d’erreur

} catch (DirectoryNotEmptyException dnee) {

// traitement en cas d’erreur

} catch (IOException ioe) {

// traitement en cas d’erreur

}

28

Exemple : supprimer un fichier (2/2)

Path path = Paths.get("C:/java/test/monfichier_copie.txt");

try {

Files.deleteIfExists(path);

} catch (DirectoryNotEmptyException dnee) {

// traitement en cas d’erreur

} catch (IOException ioe) {

// traitement en cas d’erreur

}

29

Exemple : déplacer un fichier

Path source = Paths.get("c:/java/source.txt");

Path cible = Paths.get("c:/temp/cible.txt");

try {

Files.move(source, cible, REPLACE_EXISTING, ATOMIC_MOVE);

// java.lang.UnsupportedOperationException

// Files.move(source, cible, REPLACE_EXISTING,

// COPY_ATTRIBUTES, ATOMIC_MOVE);

} catch(IOException ioe) {

// traitement en cas d’erreur

}

30

Exemple : copier un fichier

Path source = Paths.get("c:/java/fichier.txt");

Path cible = Paths.get("c:/java/fichier_copie.txt");

try {

Files.copy(source, cible, REPLACE_EXISTING,

COPY_ATTRIBUTES);

// java.lang.UnsupportedOperationException

// Files.move(source, cible, REPLACE_EXISTING,

// COPY_ATTRIBUTES, ATOMIC_MOVE);

} catch(IOException ioe) {

// traitement en cas d’erreur

}

31

Les liens symboliques

32

Les liens symboliques

Support optionnel selon le FS (Unix)

Liens symboliques suivis par défaut avec quelques exceptions : delete(), move(), walkFileTree()

Files.isSameFile() permet de vérifier si deux chemins font référence au même endroit

Files.isSymbolicLink()

Files.readSymbolicLink()

33

Exemple : créer un lien

Path lien = Paths.get("C:/java/test/monlien");

Path cible = Paths.get("C:/java/test/monfichier.txt");

Files.createLink(lien, cible);

if (Files.isSameFile(lien, cible)) {

System.out.println("Identique");

} else {

System.out.println("Non identique");

}

34

Exemple : créer un lien symbolique

Path lien = Paths.get("/home/jm/monlien");

Path cible = Paths.get("/home/jm/monfichier.txt");

Files.createSymbolicLink(lien, cible);

if (Files.isSameFile(lien, cible)) {

System.out.println("Identique");

} else {

System.out.println("Non identique");

}

35

L’interface WatchService

36

WatchService

Notifications de changements dans un répertoire

Evite d’avoir à écrire du code de type pooling sur un répertoire

Abonnement à des événements lors de la création, modification, suppression de fichiers

37

WatchService : enregistrement

Instanciation avec FileSystem.newWatchService()

Enregistrement avec WatchService.register()

WatchService watcher =

FileSystems.getDefault().newWatchService();

Path dir = Paths.get("c:/java");

WatchKey key = dir.register(watcher, ENTRY_CREATE)

38

WatchService : obtenir les événements

for (;;) {

try {

key = watcher.take();

} catch (InterruptedException ex) {

ex.printStackTrace();

}

for (WatchEvent<?> event : key.pollEvents()) {

if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) {

Path name = (Path) event.context();

System.out.format(event.kind() + " " + "%s created", name);

}

}

key.reset();

}

39

Les méta-données

40

Les attributs

Gestion complète des attributs qui sont dépendantes du système sous jacent

Taille, type d’élément, caché, …

Attributs communs (BasicFileAttributes)

ou attributs spécifiques (DosFileAttributes, PosixFileAttributes)

Gestion des permissions Posix

Méthodes de la classe Files pour en modifier un

41

Les attributs DOS

Path fichier = Paths.get("c:/java/test.txt");

FileTime now =

FileTime.fromMillis(System.currentTimeMillis());

Files.setLastModifiedTime(fichier, now);

Files.setAttribute(fichier, "dos:hidden", true);

DosFileAttributes attr = Files.readAttributes(fichier,

DosFileAttributes.class);

System.out.println(attr.isReadOnly());

System.out.println(attr.isHidden());

System.out.println(attr.isRegularFile());

System.out.println(attr.isSystem());

System.out.println(attr.lastModifiedTime());

42

Les attributs Posix

Path fichier = Paths.get("/home/jm/test.txt");

PosixFileAttributes attrs = Files.readAttributes(fichier,

PosixFileAttributes.class);

UserPrincipal owner = attrs.owner();

GroupPrincipal group = attrs.group();

System.out.println(owner);

System.out.println(group);

43

La gestion des droits Posix

Énumération PosixFilePermission

PosixFilePermissions : helper

FileAttribute : encapsule les attributs

Attention aux restrictions de droits via umask ou via le répertoire parent

Path fichier = Paths.get("/home/jm/test.txt");

Set<PosixFilePermission> perms =

PosixFilePermissions.fromString("rw-rw-rw-");

FileAttribute<Set<PosixFilePermission>> attr =

PosixFilePermissions.asFileAttribute(perms);

Files.createFile(fichier, attr);

44

Les attributs via les vues

Les vues permettent d’obtenir les attributs en bloc

Les vues sont spécialisées

Readonly ou mutable

45

Les attributs via les vues

AttributeView

FileAttributeView

BasicFileAttributeView

DosFileAttributeView

PosixFileAttributeView

FileOwnerAttributeView

AclFileAttributeView

PosixFileAttributeView

UserDefinedFileAttributeView

FileStoreAttributeView

46

Exemple avec BasicFileAttributView

Path fichier = Paths.get("c:/java/test.txt");

BasicFileAttributeView view =

Files.getFileAttributeView(fichier,

BasicFileAttributeView.class);

BasicFileAttributes attributes = view.readAttributes();

FileTime creationTime = attributes.creationTime();

FileTime lastAccessTime = attributes.lastAccessTime();

boolean isRegularFile = attributes.isRegularFile();

47

La classe FileStore

48

La classe FileStore

Encapsule un système de stockage : un disque dur, une partition, …

Obtenir des informations

FileStore Files.getFileStore(Path)

49

La classe FileStore : exemple

Path path = Paths.get("c:/test.txt");

FileStore store = Files.getFileStore(path);

long total = store.getTotalSpace() / (1024 * 1024);

long used = (store.getTotalSpace() –

store.getUnallocatedSpace()) / (1024 * 1024);

Long avail = store.getUsableSpace() / (1024 * 1024);

System.out.println("total "+total+" mb ");

50

La classe FileSystem

51

La classe FileSystem

Encapsule un système de fichiers

Obtenir celui du système par défaut ou invoquer une fabrique

FileSystem fs = FilesSystems.getDefault();

Utiliser une fabrique pour obtenir une implémentation spécifique

Fabrique pour des objets de l’API

Extensible : possibilité de créer sa propre implémentation

class MonFileSystem extends FileSystem();

52

Le séparateur du système de fichiers

String separateur = File.separator;

String separateur = FileSystems.getDefault().getSeparator();

53

Les providers de FileSystem

Il est possible d’utiliser ou de créer des fournisseurs de FileSystem

N’ont pas besoin d’être lié à un « vrai » système de fichiers

Peut permettre d’offrir différentes vues d’un système de fichiers (cacher les fichiers sensibles, accès un lecture seule, …)

java.nio.file.spi

54

Un provider FileSystem pour les zip

Permet de traiter le contenu d’un zip comme un FileSystem

Facilite l’utilisation des archives de type zip

55

Exemple : afficher un fichier d’un zip

Path jarfile = Paths.get("c:/java/archive.jar");

FileSystem fs = FileSystems.newFileSystem(jarfile, null);

Path mf = fs.getPath("META-INF", "MANIFEST.MF");

try (BufferedReader readBuffer =

Files.newBufferedReader(mf, Charset.defaultCharset())) {

String ligne = "";

while ((ligne = readBuffer.readLine()) != null) {

System.out.println(ligne);

}

}

56

Exemple : extraire un fichier d’un zip

Path jarfile = Paths.get("c:/java/archive.jar");

FileSystem fs = FileSystems.newFileSystem(jarfile, null);

Path cible = Paths.get("c:/java/MANIFEST.MF");

Files.deleteIfExists(cible);

// extaire un élément de l'archive

Files.copy(fs.getPath("/META-INF/MANIFEST.MF"), cible);

57

L’interface DirectoryStream

58

La classe DirectoryStream

Itération sur le contenu d’un répertoire

Performance sur un gros répertoire, consomme moins de ressources

Possibilité d’appliquer un filtre en utilisant un glob ou une expression régulière

Invoquer la méthode close() après utilisation

59

La classe DirectoryStream : exemple

Path dir = Paths.get("C:/java/projets");

try (DirectoryStream<Path> stream =

Files.newDirectoryStream(dir, "*.java")) {

for (Path entry : stream) {

System.out.println(entry.getFileName());

}

}

60

WalkFileTree

61

WalkFileTree

Parcourir une arborescence en utilisant le design pattern visitor (opérations récursives)

Files.walkFileTree()

FileVisitor invoqué sur chaque fichier / répertoire (pre/post)

SimpleFileVisitor : contrôle du parcours par la valeur de retour (CONTINUE, PRUNE)

Liens symboliques non suivis par défaut (FOLLOW_LINKS) : détection des références circulaires

62

WalkFileTree : exemple

Path dir = Paths.get("C:/java/projets");

Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {

public FileVisitResult visitFile(Path file,

BasicFileAttributes attrs) throws IOException {

String nom = file.getFileName().toString();

if (nom.endsWith(".java")) {

System.out.println("Fichier : " + nom);

}

return FileVisitResult.CONTINUE;

}

public FileVisitResult preVisitDirectory(Path dir,

BasicFileAttributes attrs) throws IOException {

System.out.println("Repertoire : " + dir);

return FileVisitResult.CONTINUE;

}

});

63

Lectures / écritures

Mises à jour de l’API

64

IO

Java 1.0

Synchrone

Bloquant

File InputStream OutputStream Reader Writer Socket RandomAccessFile

La gestion des io avec Java

NIO

Java 1.4 (JSR 51)

Synchrone

Non bloquant

FileChannel SocketChannel ServerSocketChannel (Charset, Selector, ByteBuffer)

NIO 2

Java 7 (JSR 203)

ASynchrone

Non bloquant

Path

AsynchronousFileChannel AsynchronousByteChannel AsynchronousSocketChannel AsynchronousServerSocketChannel

65

Obtenir des flux

Path path = Paths.get("c:/java/source.txt");

BufferedReader reader = Files.newBufferedReader(path,

Charset.defaultCharset());

BufferedWriter writer = Files.newBufferedWriter(path,

Charset.defaultCharset());

InputStream inputStream = Files.newInputStream(path);

OutputStream outputStream = Files.newOutputStream(path);

ByteChannel channel = Files.newByteChannel(path);

66

L’utilisation des méthodes

67

Lire et écrire tout le contenu

byte[] bytes = Files.readAllBytes(path);

List<String> lignes = Files.readAllLines(path,

Charset.defaultCharset());

Files.write(path, bytes);

Files.write(path, lignes, Charset.defaultCharset());

68

Exemple : écriture dans un fichier texte

Path file = Paths.get("c:/java/test/test.txt");

Charset charset = Charset.forName("UTF8");

String contenu = "Prix 10€";

try (BufferedWriter writer = Files.newBufferedWriter(file,

charset)) {

writer.write(contenu, 0, contenu.length());

} catch (IOException ioe) {

// traitement de l'erreur

}

69

L’interface SeekableByteChannel

ByteChannel qui gère une position

Channel équivalent à RandomAccessFile

Files.newSeekableByteChannel()

CREATE, CREATE_NEW, READ, WRITE, APPEND, TRUNCATE_EXISTING, NOFOLLOW_LINKS, SYNC, DSYNC...

70

L’interface SeekableByteChannel : exemple

ByteBuffer donneesBonjour = ByteBuffer.wrap("Bonjour".getBytes());

ByteBuffer donneesBonsoir = ByteBuffer.wrap("Bonsoir".getBytes());

Path path = Paths.get("C:/java/fichier.bin");

Files.deleteIfExists(path);

try (FileChannel fileChannel = FileChannel.open(path,

StandardOpenOption.CREATE, StandardOpenOption.WRITE,

StandardOpenOption.SYNC)) {

fileChannel.position(100);

fileChannel.write(donneesBonjour);

}

try (SeekableByteChannel sbc = Files.newByteChannel(path,

StandardOpenOption.WRITE, StandardOpenOption.SYNC)) {

sbc.position(200);

sbc.write(donneesBonsoir);

}

71

Canaux asynchrones

(Asynchronous I/0)

72

Canaux asynchrones

Channel avec opérations non bloquantes (connexion, lecture, écriture)

Exécution des opérations de manière asynchrone (dans un thread)

Contrôle des opérations après leur initialisation via deux solutions :

java.util.concurrent.Future

java.nio.channels.CompletionHandler

73

Canaux asynchrones avec Future

Utiliser l’objet de type Future pour connaitre le statut et le résultat de l’opération

Future.get() : obtenir le résultat (bloquant!)

Future.get() : avec un timout

Future.isDone() : l’opération est elle terminée

Future.cancel(boolean) : annuler l’opération

74

Canaux asynchrones avec CompletionHandler

Callback qui sera invoqué lorsque l’opération se termine (bien ou mal)

Paramétré avec le type de résultat et un objet en attachement (contexte qui peut être null)

interface CompletionHandler<V, A> {

void completed(V result, A attachment);

void failed(Throwable t, A attachment);

}

completed() invoqué en cas de succès

failed() invoqué en cas d’erreur

75

Exemple : dupliquer un ficher de manière asynchrone

public static void copierAsync(final AsynchronousFileChannel in,

final AsynchronousFileChannel out) {

final ByteBuffer buffer = ByteBuffer.allocate(16384);

class ReadCompletionHandler implements CompletionHandler<Integer, Integer> {

@Override

public void completed(Integer result, Integer position) {

if (result == -1) {

System.out.println("copie terminee");

return;

}

buffer.flip();

System.out.println("ecriture buffer");

out.write(buffer, position, position + result,

new CompletionHandler<Integer, Integer>() {

@Override

public void completed(Integer result, Integer newPosition) {

buffer.compact();

System.out.println("Lecture buffer");

in.read(buffer, newPosition, newPosition, ReadCompletionHandler.this);

}

76

Exemple : dupliquer un ficher de manière asynchrone

@Override

public void failed(Throwable exc, Integer attachment) {

System.out.println(exc);

throw new IOError(exc);

}

});

}

@Override

public void failed(Throwable exc, Integer attachment) {

System.out.println(exc);

throw new IOError(exc);

}

}

System.out.println("Lecture buffer");

in.read(buffer, 0, 0, new ReadCompletionHandler());

}

77

Les groupes

Les callbacks CompletionHandler sont invoqués par des threads

AsynchronousChannelGroup qui encapsule un pool de threads

DefaultThreadPool

FixedThreadPool

CachedThreadPool

78

Conclusion

79

Conclusion

NIO 2 apporte de nombreuses fonctionnalités attendues depuis longtemps

Les canaux asynchrones ne sont pas facile à utiliser mais les serveurs d’applications devraient en tirer partie

Téléchargez le JDK 7 et essayez

80

Questions

81

Merci pour votre attention

82

Licence

http://creativecommons.org/licenses/by-nc-nd/3.0/deed.fr