Eine Anleitung zu NIO2-Dateiattribut-APIs

Eine Anleitung zu NIO2-Dateiattribut-APIs

1. Überblick

In diesem Artikel untersuchen wir eine der erweiterten Funktionen der Java 7 NIO.2-Dateisystem-APIs, insbesondere der Dateiattribut-APIs.

Wir haben zuvor dieFile undPath APIs behandelt, wenn Sie zuerst tiefer in diese grundlegenden Teile eintauchen möchten.

Alle Dateien, die für die Ausführung von Dateisystemvorgängen erforderlich sind, sind injava.nio.file package zusammengefasst:

import java.nio.file.*;

2. Grundlegende Dateiattribute

Beginnen wir mit einer allgemeinen Ansicht der grundlegenden Attribute, die allen Dateisystemen gemeinsam sind - bereitgestellt durchBasicFileAttributeView - und in der alle obligatorischen und optionalen sichtbaren Dateiattribute gespeichert sind.

Wir können die grundlegenden Attribute des Benutzerstandorts auf dem aktuellen Computer untersuchen, indem wir einen Pfad zu HOME erstellen und die grundlegende Attributansicht abrufen:

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

Nach dem obigen Schritt können wir nun alle Attribute des Pfads lesen, auf den in einer Massenoperation verwiesen wird:

BasicFileAttributes basicAttribs = basicView.readAttributes();

Wir sind jetzt in der Lage, verschiedene gemeinsame Attribute zu untersuchen, die wir in unseren Anwendungen, insbesondere in bedingten Anweisungen, tatsächlich verwenden können.

Wir können die Größe der Datei aus dem Container mit den grundlegenden Attributen abfragen:

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

Wir können auch überprüfen, ob es sich um ein Verzeichnis handelt:

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

Oder eine reguläre Datei:

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

Mit Java NIO.2 können wir nun symbolische Links oder Softlinks im Dateisystem verarbeiten. Dies sind Dateien oder Verzeichnisse, die wir normalerweise als Verknüpfungen bezeichnen.

So überprüfen Sie, ob eine Datei eine symbolische Verknüpfung ist:

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

In seltenen Fällen können wir die API vonisOtheraufrufen, um zu überprüfen, ob die Datei zu keiner der allgemeinen Kategorien von regulären Dateien, Verzeichnissen oder symbolischen Links gehört:

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

So ermitteln Sie die Uhrzeit, zu der die Datei erstellt wurde:

FileTime created = basicAttribs.creationTime();

So rufen Sie die letzte geänderte Zeit ab:

FileTime modified = basicAttribs.lastModifiedTime();

Und um die letzte Zugriffszeit zu erhalten:

FileTime accessed = basicAttribs.lastAccessTime();

Alle obigen Beispiele geben das ObjektFileTimezurück. Dies ist eine brauchbarere Abstraktion als nur ein Zeitstempel.

Beispielsweise können zwei Dateizeiten einfach verglichen werden, um zu ermitteln, welches Ereignis vor oder nach dem anderen aufgetreten ist:

@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));
}

DiecompareTo-API funktioniert genauso wie bei anderen Vergleichsdaten in Java. Es wird ein negativer Wert zurückgegeben, falls das Objekt, für das es aufgerufen wird, kleiner als das Argument ist. In unserem Fall liegt die Erstellungszeit definitiv vor der Zugriffszeit, wie in der ersten Behauptung.

In der zweiten Zusicherung erhalten wir einen positiven ganzzahligen Wert, da eine Änderung erst nach einem Erstellungsereignis vorgenommen werden kann. Und schließlich wird 0 zurückgegeben, wenn die verglichenen Zeiten gleich sind.

Wenn wir ein FileTime-Objekt haben, können wir es je nach Bedarf in die meisten anderen Einheiten konvertieren. Tage, Stunden, Minuten, Sekunden, Millisekunden und so weiter. Dazu rufen wir die entsprechende API auf:

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

Wir können auch eine lesbare Form der Dateizeit drucken, indem wir die API vontoStringaufrufen:

accessed.toString();

Welche druckt etwas Nützliches im ISO-Zeitformat:

2016-11-24T07:52:53.376Z

Wir können die Zeitattribute in der Ansicht auch ändern, indem wir diesetTimes(modified, accessed, created)-API aufrufen. Wir übergeben die neuenFileTime-Objekte, an denen wir uns ändern möchten, oder null, an denen wir uns nicht ändern möchten.

Gehen Sie folgendermaßen vor, um die letzte Zugriffszeit eine Minute in der Zukunft zu ändern:

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

Diese Änderung bleibt in der eigentlichen Datei erhalten, wie Sie von jeder anderen Anwendung auf dem Computer, die das Dateisystem verwendet, sehen können.

3. Dateibereichsattribute

Wenn Siemy computer unter Windows, Linux oder Mac öffnen, wird normalerweise eine grafische Analyse der Speicherplatzinformationen zu Ihren Speicherlaufwerken angezeigt.

Mit Java NIO.2 ist diese Art von High-Level-Funktionalität sehr einfach. Es interagiert mit dem zugrunde liegenden Dateisystem, um diese Informationen abzurufen, während wir nur einfache APIs aufrufen müssen.

Wir können dieFileStore-Klasse verwenden, um Speicherlaufwerke zu überprüfen und wichtige Informationen zu erhalten, z. B. die Größe, den verwendeten Speicherplatz und den noch nicht verwendeten Speicherplatz.

Um eineFileStore-Instanz für den Speicherort einer beliebigen Datei im Dateisystem abzurufen, verwenden wir diegetFileStore-API derFiles-Klasse:

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

DieseFileStore-Instanz repräsentiert speziell den Dateispeicher, in dem sich die angegebene Datei befindet, nicht die Datei selbst. So erhalten Sie den gesamten Speicherplatz:

long total = store.getTotalSpace();

So nutzen Sie den Platz:

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

Es ist weniger wahrscheinlich, dass wir diesem Ansatz folgen als dem nächsten.

In der Regel erhalten wir Informationen zu Speicherinformationen für alle Dateispeicher. Ummy computer's Grafikspeicherplatzinformationen in einem Programm zu emulieren, können wir die Dateispeicher mit der KlasseFileSystem auflisten:

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

Wir können dann die zurückgegebenen Werte durchlaufen und alles tun, was wir brauchen, um die Informationen zu verarbeiten, z. B. eine grafische Benutzeroberfläche zu aktualisieren:

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

Beachten Sie, dass alle zurückgegebenen Werte in Byte angegeben sind. Wir können in geeignete Einheiten konvertieren und andere Informationen, wie z. B. den belegten Raum, mithilfe von Grundrechenarten berechnen.

The difference between unallocated space and usable space ist für die JVM zugänglich.

Verwendbarer Speicherplatz ist der für die JVM verfügbare Speicherplatz, während nicht zugewiesener Speicherplatz der verfügbare Speicherplatz ist, der vom zugrunde liegenden Dateisystem angezeigt wird. Daher kann der nutzbare Speicherplatz manchmal kleiner als der nicht zugewiesene Speicherplatz sein.

4. Dateibesitzerattribute

Um die Informationen zum Dateibesitz zu überprüfen, verwenden wir dieFileOwnerAttributeView-Schnittstelle. Es gibt uns einen Überblick über die Eigentumsinformationen.

Wir können einFileOwnerAttributeView-Objekt wie folgt erstellen:

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

So rufen Sie den Eigentümer der Datei aus der obigen Ansicht ab:

UserPrincipal owner = ownerView.getOwner();

Wir können mit dem obigen Objekt nicht viel programmgesteuert tun, außer den Namen des Eigentümers für einen anderen beliebigen Zweck abzurufen:

String ownerName = owner.toString();

5. Benutzerdefinierte Dateiattribute

Es gibt Szenarien, in denen die im Dateisystem definierten Dateiattribute für Ihre Anforderungen nicht ausreichen. Wenn Sie auf einen solchen Fall stoßen und Ihre eigenen Attribute für eine Datei festlegen müssen, ist dieUserDefinedFileAttributeView-Schnittstelle hilfreich:

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

So rufen Sie die Liste der benutzerdefinierten Attribute ab, die bereits für die in der obigen Ansicht dargestellte Datei definiert sind:

List attribList = userDefView.list();

Um ein benutzerdefiniertes Attribut für die Datei festzulegen, verwenden wir die folgende Redewendung:

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

Wenn Sie auf die benutzerdefinierten Attribute zugreifen müssen, können Sie die von der Ansicht zurückgegebene Attributliste durchlaufen und diese anhand der folgenden Redewendung überprüfen:

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

Um ein benutzerdefiniertes Attribut aus der Datei zu entfernen, rufen wir einfach die Lösch-API der Ansicht auf:

userDefView.delete(attrName);

6. Fazit

In diesem Artikel haben wir einige der weniger häufig verwendeten Funktionen untersucht, die in den Java 7 NIO.2-Dateisystem-APIs verfügbar sind, insbesondere die Dateiattribut-APIs.

Der vollständige Quellcode für die in diesem Artikel verwendeten Beispiele ist inGithub project verfügbar.