Guide sur les API d’attributs de fichier NIO2

Guide des API d'attributs de fichier NIO2

1. Vue d'ensemble

Dans cet article, nous allons explorer l'une des fonctionnalités avancées des API de système de fichiers Java 7 NIO.2, à savoir les API d'attributs de fichier.

Nous avons déjà couvert lesFile etPath APIs si vous souhaitez d'abord approfondir ces éléments fondamentaux.

Tous les fichiers nécessaires pour gérer les opérations du système de fichiers sont regroupés dans lesjava.nio.file package:

import java.nio.file.*;

2. Attributs de fichier de base

Commençons par une vue de haut niveau des attributs de base communs à tous les systèmes de fichiers - fournis par leBasicFileAttributeView - qui stocke tous les attributs de fichier visibles obligatoires et facultatifs.

Nous pouvons explorer les attributs de base de l'emplacement du domicile de l'utilisateur sur la machine actuelle, en créant un chemin vers HOME et en obtenant sa vue d'attributs de base:

String HOME = System.getProperty("user.home");
Path home = Paths.get(HOME);
BasicFileAttributeView basicView =
  Files.getFileAttributeView(home, BasicFileAttributeView.class);

Après l'étape ci-dessus, nous pouvons maintenant lire tous les attributs du chemin pointé en une seule opération en bloc:

BasicFileAttributes basicAttribs = basicView.readAttributes();

Nous sommes maintenant en mesure d'explorer différents attributs communs que nous pouvons réellement utiliser dans nos applications, en particulier dans les instructions conditionnelles.

Nous pouvons interroger la taille du fichier à partir de son conteneur d'attributs de base:

@Test
public void givenPath_whenGetsFileSize_thenCorrect() {
    long size = basicAttribs.size();
    assertTrue(size > 0);
}

Nous pouvons également vérifier s’il s’agit d’un répertoire:

@Test
public void givenPath_whenChecksIfDirectory_thenCorrect() {
    boolean isDir = basicAttribs.isDirectory();
    assertTrue(isDir);
}

Ou un fichier régulier:

@Test
public void givenPath_whenChecksIfFile_thenCorrect() {
    boolean isFile = basicAttribs.isRegularFile();
    assertFalse(isFile);
}

Avec Java NIO.2, nous sommes maintenant en mesure de traiter des liens symboliques ou des liens symboliques dans le système de fichiers. Ce sont des fichiers ou des répertoires que nous appelons normalement des raccourcis.

Pour vérifier si un fichier est un lien symbolique:

@Test
public void givenPath_whenChecksIfSymLink_thenCorrect() {
    boolean isSymLink = basicAttribs.isSymbolicLink();
    assertFalse(isSymLink);
}

Dans de rares cas, nous pouvons appeler l'APIisOther pour vérifier si le fichier n'appartient à aucune des catégories courantes de fichier régulier, de répertoire ou de lien symbolique:

@Test
public void givenPath_whenChecksIfOther_thenCorrect() {
    boolean isOther = basicAttribs.isOther();
    assertFalse(isOther);
}

Pour obtenir l'heure à laquelle le fichier a été créé:

FileTime created = basicAttribs.creationTime();

Pour obtenir la dernière heure modifiée:

FileTime modified = basicAttribs.lastModifiedTime();

Et pour obtenir la dernière heure d'accès:

FileTime accessed = basicAttribs.lastAccessTime();

Tous les exemples ci-dessus renvoient un objetFileTime. C'est une abstraction plus utilisable qu'un simple horodatage.

Par exemple, nous pouvons facilement comparer deux temps de fichier pour savoir quel événement s'est produit avant ou après l'autre:

@Test
public void givenFileTimes_whenComparesThem_ThenCorrect() {
    FileTime created = basicAttribs.creationTime();
    FileTime modified = basicAttribs.lastModifiedTime();
    FileTime accessed = basicAttribs.lastAccessTime();

    assertTrue(0 >= created.compareTo(accessed));
    assertTrue(0 <= modified.compareTo(created));
    assertTrue(0 == created.compareTo(created));
}

L'APIcompareTo fonctionne de la même manière que pour les autres comparables en Java. Il renvoie une valeur négative au cas où l’objet sur lequel il est appelé est inférieur à l’argument; dans notre cas, le temps de création précède définitivement le temps d'accès comme dans la première assertion.

Dans la deuxième assertion, nous obtenons une valeur entière positive car une modification ne peut être effectuée qu'après un événement de création. Et finalement, il retourne 0 lorsque les temps comparés sont égaux.

Lorsque nous avons un objet FileTime, nous pouvons le convertir en la plupart des autres unités en fonction de nos besoins. jours, heures, minutes, secondes, millisecondes et ainsi de suite. Nous faisons cela en appelant l'API appropriée:

accessed.to(TimeUnit.SECONDS);
accessed.to(TimeUnit.HOURS);
accessed.toMillis();

Nous pouvons également imprimer une forme lisible par l'homme de l'heure du fichier en appelant son APItoString:

accessed.toString();

Qui imprime quelque chose d’utile au format heure ISO:

2016-11-24T07:52:53.376Z

Nous pouvons également modifier les attributs de temps sur la vue en appelant son APIsetTimes(modified, accessed, created). Nous transmettons les nouveaux objetsFileTime où nous voulons changer ou null où nous ne voulons pas changer.

Pour modifier l'heure du dernier accès une minute dans le futur, procédez comme suit:

FileTime newAccessTime = FileTime.fromMillis(
  basicAttribs.lastAccessTime().toMillis() + 60000);
basicView.setTimes(null, newAccessTime , null);

Cette modification persistera dans le fichier réel, comme dans n'importe quelle autre application exécutée sur la machine et utilisant le système de fichiers.

3. Attributs d'espace fichier

Lorsque vous ouvrezmy computer sous Windows, Linux ou Mac, vous pouvez généralement voir une analyse graphique des informations d'espace sur vos disques de stockage.

Java NIO.2 facilite grandement ce type de fonctionnalité de haut niveau. Il interagit avec le système de fichiers sous-jacent pour extraire ces informations alors que nous n'avons qu'à appeler des API simples.

Nous pouvons utiliser la classeFileStore pour inspecter les lecteurs de stockage et obtenir des informations importantes telles que leur taille, la quantité d’espace utilisée et la quantité encore inutilisée.

Pour obtenir une instanceFileStore pour l'emplacement d'un fichier arbitraire dans le système de fichiers, nous utilisons l'APIgetFileStore de la classeFiles:

Path file = Paths.get("file");
FileStore store = Files.getFileStore(file);

Cette instance deFileStore représente spécifiquement le magasin de fichiers où se trouve le fichier spécifié, pas le fichier lui-même. Pour obtenir un espace total:

long total = store.getTotalSpace();

Pour obtenir de l'espace utilisé:

long used = store.getTotalSpace() - store.getUnallocatedSpace();

Nous sommes moins susceptibles de suivre cette approche que la suivante.

Plus généralement, nous allons probablement obtenir des informations sur les informations de stockage de tous les magasins de fichiers. Pour émuler les informations d'espace disque graphiquemy computer's dans un programme, nous pouvons utiliser la classeFileSystem pour énumérer les magasins de fichiers:

Iterable fileStores = FileSystems.getDefault().getFileStores();

Nous pouvons ensuite parcourir les valeurs renvoyées et faire ce que nous devons faire avec les informations, telles que la mise à jour d'une interface utilisateur graphique:

for (FileStore fileStore : fileStores) {
    long totalSpace = fileStore.getTotalSpace();
    long unAllocated = fileStore.getUnallocatedSpace();
    long usable = fileStore.getUsableSpace();
}

Notez que toutes les valeurs renvoyées sont en octets. Nous pouvons convertir en unités appropriées et calculer d'autres informations, telles que l'espace utilisé, en utilisant l'arithmétique de base.

The difference between unallocated space and usable space est accessible à la JVM.

L'espace utilisable est l'espace disponible pour la machine virtuelle Java, tandis que l'espace non alloué est l'espace disponible tel qu'il est vu par le système de fichiers sous-jacent. Par conséquent, l'espace utilisable peut parfois être plus petit que l'espace non alloué.

4. Attributs du propriétaire de fichier

Pour inspecter les informations de propriété des fichiers, nous utilisons l'interfaceFileOwnerAttributeView. Cela nous donne une vue d'ensemble des informations sur la propriété.

Nous pouvons créer un objetFileOwnerAttributeView comme ceci:

Path path = Paths.get(HOME);
FileOwnerAttributeView ownerView = Files.getFileAttributeView(
  attribPath, FileOwnerAttributeView.class);

Pour obtenir le propriétaire du fichier à partir de la vue ci-dessus:

UserPrincipal owner = ownerView.getOwner();

Il n'y a vraiment rien que nous puissions faire par programme avec l'objet ci-dessus, mis à part obtenir le nom du propriétaire à d'autres fins arbitraires:

String ownerName = owner.toString();

5. Attributs de fichier définis par l'utilisateur

Il existe des scénarios dans lesquels les attributs de fichier définis dans le système de fichiers ne répondent pas à vos besoins. Si vous rencontrez un tel cas et que vous avez besoin de définir vos propres attributs sur un fichier, l'interfaceUserDefinedFileAttributeView vous sera utile:

Path path = Paths.get("somefile");
UserDefinedFileAttributeView userDefView = Files.getFileAttributeView(
  attribPath, UserDefinedFileAttributeView.class);

Pour récupérer la liste des attributs définis par l'utilisateur déjà définis pour le fichier représenté par la vue ci-dessus:

List attribList = userDefView.list();

Pour définir un attribut défini par l'utilisateur sur le fichier, nous utilisons l'idiome suivant:

String name = "attrName";
String value = "attrValue";
userDefView.write(name, Charset.defaultCharset().encode(value));

Lorsque vous devez accéder aux attributs définis par l'utilisateur, vous pouvez parcourir la liste d'attributs renvoyée par la vue et les inspecter à l'aide de cet idiome:

ByteBuffer attrValue = ByteBuffer.allocate(userView.size(attrName));
userDefView.read(attribName, attribValue);
attrValue.flip();
String attrValue = Charset.defaultCharset().decode(attrValue).toString();

Pour supprimer un attribut défini par l'utilisateur du fichier, nous appelons simplement l'API de suppression de la vue:

userDefView.delete(attrName);

6. Conclusion

Dans cet article, nous avons exploré certaines des fonctionnalités les moins couramment utilisées disponibles dans les API de système de fichiers Java 7 NIO.2, notamment les API d'attributs de fichier.

Le code source complet des exemples utilisés dans cet article est disponible dans leGithub project.