Java NIO2 Path API

1. Overzicht

In dit artikel leren we hoe we de nieuwe I / O (NIO2) kunnen gebruiken Pad API in Java.

De Pad API's in NIO2 vormen een van de belangrijkste nieuwe functionele gebieden die bij Java 7 zijn geleverd en specifiek een subset van de nieuwe bestandssysteem-API naast File API's.

2. Installatie

De NIO2-ondersteuning is gebundeld in de java.nio.file pakket. Dus het opzetten van uw project om de Pad API's zijn gewoon een kwestie van alles in dit pakket importeren:

importeer java.nio.file. *;

Aangezien de codevoorbeelden in dit artikel waarschijnlijk in verschillende omgevingen zullen worden uitgevoerd, gaan we de homedirectory van de gebruiker onder de loep nemen:

private static String HOME = System.getProperty ("user.home");

Deze variabele verwijst naar een geldige locatie in elke omgeving.

De Paden class is het belangrijkste toegangspunt voor alle bewerkingen met bestandssysteempaden. Het stelt ons in staat om paden naar bestanden en mappen te maken en te manipuleren.

Opgemerkt moet worden dat padbewerkingen voornamelijk syntactisch van aard zijn; ze hebben geen effect op het onderliggende bestandssysteem en evenmin heeft het bestandssysteem enig effect op het al dan niet slagen ervan. Dit betekent dat het doorgeven van een niet-bestaand pad als parameter van een padbewerking niet van invloed is op het al dan niet slagen ervan.

3. Padbewerkingen

In deze sectie zullen we de belangrijkste syntaxis introduceren die wordt gebruikt in padbewerkingen. Zoals de naam al aangeeft, is de Pad class is een programmatische weergave van een pad in het bestandssysteem.

EEN Pad object bevat de bestandsnaam en directorylijst die worden gebruikt om het pad te construeren en wordt gebruikt om bestanden te onderzoeken, te lokaliseren en te manipuleren.

De helper klasse, java.nio.file.Paths (in meervoud) is de formele manier van creëren Pad voorwerpen. Het heeft twee statische methoden om een Pad van een padtekenreeks:

Path path = Paths.get ("path string");

Of we nu een forward of backslash in het pad gebruiken Draad, maakt niet uit, de API lost deze parameter op volgens de vereisten van het onderliggende bestandssysteem.

En van een java.net.URI voorwerp:

Padpad = Paths.get (URI-object);

We kunnen nu doorgaan en deze in actie zien.

4. Een pad creëren

Naar Maak een Pad object uit een padtekenreeks:

@Test openbare leegte gegevenPathString_whenCreatesPathObject_thenCorrect () {Pad p = Paths.get ("/ artikelen / baeldung"); assertEquals ("\ artikelen \ baeldung", p.toString ()); }

De krijgen API kan een variabele argumentenparameter van padstringdelen aannemen (in dit geval Lidwoord en baeldung) naast het eerste deel (in dit geval Lidwoord).

Als we deze onderdelen leveren in plaats van een volledige padstring, zullen ze worden gebruikt om het Path-object te construeren, we hoeven de naamscheidingstekens (slashes) niet op te nemen in het variabele argumentengedeelte:

@Test openbare leegte gegevenPathParts_whenCreatesPathObject_thenCorrect () {Pad p = Paths.get ("/ artikelen", "baeldung"); assertEquals ("\ artikelen \ baeldung", p.toString ()); }

5. Padinformatie ophalen

U kunt het Path-object zien als naamelementen als een reeks. Een pad Draad zoals E: \ baeldung \ artikelen \ java bestaat uit drie naamelementen, d.w.z. baeldung, Lidwoord, en Java. Het hoogste element in de directorystructuur zou zich op index 0 bevinden, in dit geval dus baeldung.

Het laagste element in de directorystructuur bevindt zich op index [n-1], waar n is het aantal naamelementen in het pad. Dit laagste element wordt de bestandsnaam ongeacht of het een echt bestand is of niet:

@Test openbare leegte gegevenPath_whenRetrievesFileName_thenCorrect () {Pad p = Paths.get ("/ artikelen / baeldung / logs"); Pad bestandsnaam = p.getFileName (); assertEquals ("logs", bestandsnaam.toString ()); }

Er zijn methoden beschikbaar voor het ophalen van individuele elementen op index:

@Test openbare ongeldig gegevenPath_whenRetrievesNameByIndex_thenCorrect () {Pad p = Paths.get ("/ artikelen / baeldung / logs"); Padnaam0 = getName (0); Padnaam1 = getName (1); Padnaam2 = getName (2); assertEquals ("artikelen", name0.toString ()); assertEquals ("baeldung", name1.toString ()); assertEquals ("logs", name2.toString ()); }

of een subreeks van het pad met behulp van deze indexbereiken:

@Test openbare leegte gegevenPath_whenCanRetrieveSubsequenceByIndex_thenCorrect () {Pad p = Paths.get ("/ artikelen / baeldung / logs"); Pad subPath1 = p.subpath (0,1); Pad subPath2 = p.subpad (0,2); assertEquals ("artikelen", subPath1.toString ()); assertEquals ("artikelen \ baeldung", subPath2.toString ()); assertEquals ("artikelen \ baeldung \ logs", p.subpath (0, 3) .toString ()); assertEquals ("baeldung", p.subpath (1, 2) .toString ()); assertEquals ("baeldung \ logs", p.subpath (1, 3) .toString ()); assertEquals ("logs", p.subpath (2, 3) .toString ()); }

Elk pad is gekoppeld aan een bovenliggend pad of nul als het pad geen ouder heeft. Het bovenliggende element van een path-object bestaat uit de rootcomponent van het pad, indien aanwezig, en elk element in het pad behalve de bestandsnaam. Als voorbeeld is het bovenliggende pad van /abc is / a / b en dat van /een is niets:

@Test openbare leegte gegevenPath_whenRetrievesParent_thenCorrect () {Pad p1 = Paths.get ("/ artikelen / baeldung / logs"); Pad p2 = Paths.get ("/ artikelen / baeldung"); Pad p3 = Paths.get ("/ artikelen"); Pad p4 = Paths.get ("/"); Pad parent1 = p1.getParent (); Pad parent2 = p2.getParent (); Pad parent3 = p3.getParent (); Pad parent4 = p4.getParenth (); assertEquals ("\ artikelen \ baeldung", parent1.toString ()); assertEquals ("\ artikelen", parent2.toString ()); assertEquals ("\", parent3.toString ()); assertEquals (null, parent4); }

We kunnen ook het root-element van een pad ophalen:

@Test openbare leegte gegevenPath_whenRetrievesRoot_thenCorrect () {Pad p1 = Paths.get ("/ artikelen / baeldung / logs"); Pad p2 = Paths.get ("c: / artikelen / baeldung / logs"); Pad root1 = p1.getRoot (); Pad root2 = p2.getRoot (); assertEquals ("\", root1.toString ()); assertEquals ("c: \", root2.toString ()); }

6. Een pad normaliseren

Veel bestandssystemen gebruiken “.” notatie om de huidige directory aan te duiden en “..” om de bovenliggende directory aan te duiden. Mogelijk hebt u een situatie waarin een pad overtollige directory-informatie bevat.

Overweeg bijvoorbeeld de volgende padstrings:

/baeldung/./articles /baeldung/authors/../articles / baeldung / artikelen

Ze besluiten allemaal naar dezelfde locatie / baeldung / artikelen. De eerste twee hebben ontslagen, de laatste niet.

Het normaliseren van een pad omvat het verwijderen van overtolligheden erin. De Path.normalize () bediening is voor dit doel voorzien.

Dit voorbeeld zou nu voor zichzelf moeten spreken:

@Test openbare leegte gegevenPath_whenRemovesRedundancies_thenCorrect1 () {Pad p = Paths.get ("/ home /./ baeldung / artikelen"); Pad cleanPath = p.normalize (); assertEquals ("\ home \ baeldung \ artikelen", cleanPath.toString ()); }

Deze ook:

@Test openbare leegte gegevenPath_whenRemovesRedundancies_thenCorrect2 () {Pad p = Paths.get ("/ home / baeldung /../ artikelen"); Pad cleanPath = p.normalize (); assertEquals ("\ home \ artikelen", cleanPath.toString ()); }

7. Padconversie

Er zijn bewerkingen om een ​​pad naar een gekozen presentatieformaat te converteren. Om een ​​pad om te zetten in een string die vanuit de browser kan worden geopend, gebruiken we de toUri methode:

@Test openbare leegte gegevenPath_whenConvertsToBrowseablePath_thenCorrect () {Pad p = Paths.get ("/ home / baeldung / artikelen.html"); URI uri = p.toUri (); assertEquals ("file: /// E: /home/baeldung/articles.html", uri.toString ()); }

We kunnen een pad ook converteren naar zijn absolute representatie. De naarAbsolutePath methode lost een pad op tegen de standaardmap van een bestandssysteem:

@Test openbare leegte gegevenPath_whenConvertsToAbsolutePath_thenCorrect () {Pad p = Paths.get ("/ home / baeldung / artikelen.html"); Pad absPath = p.toAbsolutePath (); assertEquals ("E: \ home \ baeldung \ artikelen.html", absPath.toString ()); }

Wanneer echter wordt gedetecteerd dat het pad dat moet worden opgelost al absoluut is, retourneert de methode het zoals het is:

@Test openbare leegte gegevenAbsolutePath_whenRetainsAsAbsolute_thenCorrect () {Pad p = Paths.get ("E: \ home \ baeldung \ artikelen.html"); Pad absPath = p.toAbsolutePath (); assertEquals ("E: \ home \ baeldung \ artikelen.html", absPath.toString ()); }

We kunnen ook elk pad naar zijn echte equivalent converteren door de toRealPath methode. Deze methode probeert het pad op te lossen door de elementen toe te wijzen aan daadwerkelijke mappen en bestanden in het bestandssysteem.

Tijd om de variabele te gebruiken die we in de Opstelling sectie die verwijst naar de thuislocatie van de ingelogde gebruiker in het bestandssysteem:

@Test openbare ongeldig gegevenExistingPath_whenGetsRealPathToFile_thenCorrect () {Pad p = Paths.get (HOME); Pad realPath = p.toRealPath (); assertEquals (HOME, realPath.toString ()); }

De bovenstaande test vertelt ons niet echt veel over het gedrag van deze operatie. Het meest voor de hand liggende resultaat is dat als het pad niet bestaat in het bestandssysteem, de bewerking een IOException, Lees verder.

Bij gebrek aan een betere manier om dit punt naar huis te rijden, kijk maar eens naar de volgende test, die probeert een niet-bestaand pad om te zetten in een echt pad:

@Test (verwacht = NoSuchFileException.class) openbare ongeldige gegevenInExistentPath_whenFailsToConvert_thenCorrect () {Pad p = Paths.get ("E: \ home \ baeldung \ artikelen.html"); p.toRealPath (); }

De test slaagt als we een IOException. De feitelijke subklasse van IOException dat deze operatie gooit is NoSuchFileException.

8. Paden samenvoegen

U kunt twee willekeurige paden samenvoegen met de extensie oplossen methode.

Simpel gezegd, we kunnen de oplossen methode op elke Pad en geef een gedeeltelijk pad als argument. Dat gedeeltelijke pad wordt toegevoegd aan het oorspronkelijke pad:

@Test openbare leegte gegevenTwoPaths_whenJoinsAndResolves_thenCorrect () {Pad p = Paths.get ("/ baeldung / artikelen"); Pad p2 = p.resolve ("java"); assertEquals ("\ baeldung \ artikelen \ java", p2.toString ()); }

Wanneer de padtekenreeks echter is doorgegeven aan de oplossen methode is niet een gedeeltelijk pad; met name een absoluut pad, waarna het doorgegeven pad wordt geretourneerd:

@Test openbare leegte gegevenAbsolutePath_whenResolutionRetainsIt_thenCorrect () {Pad p = Paths.get ("/ baeldung / artikelen"); Pad p2 = p.resolve ("C: \ baeldung \ artikelen \ java"); assertEquals ("C: \ baeldung \ artikelen \ java", p2.toString ()); }

Hetzelfde gebeurt met elk pad dat een root-element heeft. De padreeks "Java" heeft geen root-element terwijl de path string "/Java" heeft een wortelelement. Daarom, wanneer u een pad met een root-element passeert, wordt het geretourneerd zoals het is:

@Test openbare leegte gegevenPathWithRoot_whenResolutionRetainsIt_thenCorrect2 () {Pad p = Paths.get ("/ baeldung / artikelen"); Pad p2 = p.resolve ("/ java"); assertEquals ("\ java", p2.toString ()); }

9. Relativeren Paden

De voorwaarde relativeren betekent gewoon een direct pad creëren tussen twee bekende paden. Als we bijvoorbeeld een directory hebben / baeldung en daarin hebben we twee andere mappen zodat / baeldung / auteurs en / baeldung / artikelen zijn geldige paden.

Het pad naar Lidwoord ten opzichte van auteurs zou worden beschreven als "Ga een niveau omhoog in de directoryhiërarchie en vervolgens naar de artikeldirectory" of ..\Lidwoord:

@Test openbare leegte gegevenSiblingPaths_whenCreatesPathToOther_thenCorrect () {Pad p1 = Paths.get ("artikelen"); Pad p2 = Paths.get ("auteurs"); Pad p1_rel_p2 = p1.relativize (p2); Pad p2_rel_p1 = p2.relativize (p1); assertEquals (".. \ auteurs", p1_rel_p2.toString ()); assertEquals (".. \ artikelen", p2_rel_p1.toString ()); }

Ervan uitgaande dat we het Lidwoord directory naar auteurs map zodanig dat ze niet langer broers of zussen zijn. De volgende relativerende bewerkingen omvatten het creëren van een pad tussen baeldung en Lidwoord en vice versa:

@Test openbare leegte gegevenNonSiblingPaths_whenCreatesPathToOther_thenCorrect () {Pad p1 = Paths.get ("/ baeldung"); Pad p2 = Paths.get ("/ baeldung / auteurs / artikelen"); Pad p1_rel_p2 = p1.relativize (p2); Pad p2_rel_p1 = p2.relativize (p1); assertEquals ("auteurs \ artikelen", p1_rel_p2.toString ()); assertEquals (".. \ ..", p2_rel_p1.toString ()); }

10. Paden vergelijken

De Pad class heeft een intuïtieve implementatie van de is gelijk aan methode waarmee we twee paden voor gelijkheid kunnen vergelijken:

@Test openbare ongeldig gegevenTwoPaths_whenTestsEquality_thenCorrect () {Pad p1 = Paths.get ("/ baeldung / artikelen"); Pad p2 = Paths.get ("/ baeldung / artikelen"); Pad p3 = Paths.get ("/ baeldung / auteurs"); assertTrue (p1.equals (p2)); assertFalse (p1.equals (p3)); }

Je kunt ook controleren of een pad begint met een bepaalde string:

@Test openbare ongeldig gegevenPath_whenInspectsStart_thenCorrect () {Pad p1 = Paths.get ("/ baeldung / artikelen"); assertTrue (p1.startsWith ("/ baeldung")); }

Of eindigt met een andere string:

@Test openbare leegte gegevenPath_whenInspectsEnd_thenCorrect () {Pad p1 = Paths.get ("/ baeldung / artikelen"); assertTrue (p1.endsWith ("artikelen")); }

11. Conclusie

In dit artikel hebben we padbewerkingen laten zien in de nieuwe bestandssysteem-API (NIO2) die werd geleverd als onderdeel van Java 7 en de meeste daarvan in actie zagen.

De codevoorbeelden die in dit artikel worden gebruikt, zijn te vinden in het Github-project van het artikel.