Java NIO2 Path API

1. Oversikt

I denne artikkelen vil vi lære hvordan du bruker den nye I / O (NIO2) Sti API i Java.

De Sti API-er i NIO2 utgjør et av de viktigste nye funksjonsområdene som ble levert med Java 7, og spesielt et delsett av det nye filsystem-API-et sammen med File API-er.

2. Oppsett

NIO2-støtten er samlet i java.nio.file pakke. Så sette opp prosjektet ditt for å bruke Sti APIer er bare å importere alt i denne pakken:

importer java.nio.file. *;

Siden kodeeksemplene i denne artikkelen sannsynligvis vil kjøre i forskjellige miljøer, la oss ta hånd om hjemmekatalogen til brukeren:

privat statisk streng HOME = System.getProperty ("user.home");

Denne variabelen vil peke på et gyldig sted i ethvert miljø.

De Stier klasse er hovedinngangsstedet for alle operasjoner som involverer filsystembaner. Det lar oss lage og manipulere stier til filer og kataloger.

Verdt å merke seg er at stioperasjoner hovedsakelig er syntaktiske; de har ingen innvirkning på det underliggende filsystemet, og heller ikke har filsystemet noen innvirkning på om de lykkes eller mislykkes. Dette betyr at å sende en ikke-eksisterende bane som en parameter for en baneoperasjon ikke har noen betydning for om den lykkes eller mislykkes.

3. Stioperasjoner

I denne delen vil vi introdusere hovedsyntaxen som brukes i baneoperasjoner. Som navnet antyder, har Sti klasse er en programmatisk fremstilling av en bane i filsystemet.

EN Sti objektet inneholder filnavnet og kataloglisten som brukes til å konstruere banen og brukes til å undersøke, finne og manipulere filer.

Hjelperklassen, java.nio.file. stier (i flertallsform) er den formelle måten å skape på Sti gjenstander. Den har to statiske metoder for å lage en Sti fra en banestreng:

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

Enten vi bruker en fremover eller tilbakeslag i banen Streng, spiller ingen rolle, APIen løser denne parameteren i henhold til det underliggende filsystemets krav.

Og fra en java.net.URI gjenstand:

Banesti = Paths.get (URI-objekt);

Vi kan nå gå videre og se disse i aksjon.

4. Opprette en bane

Til lage en Sti objekt fra en banestreng:

@Test offentlig ugyldighet givenPathString_whenCreatesPathObject_thenCorrect () {Path p = Paths.get ("/ articles / baeldung"); assertEquals ("\ artikler \ baeldung", p.toString ()); }

De API kan ta en variabel argumentparameter for banestrengdeler (i dette tilfellet, artikler og baeldung) i tillegg til første del (i dette tilfellet, artikler).

Hvis vi oppgir disse delene i stedet for en komplett banestreng, vil de bli brukt til å konstruere Path-objektet.

@Test offentlig ugyldig givenPathParts_whenCreatesPathObject_thenCorrect () {Path p = Paths.get ("/ articles", "baeldung"); assertEquals ("\ artikler \ baeldung", p.toString ()); }

5. Henter stiinformasjon

Du kan tenke på Path-objektet som navnelementer som en sekvens. En vei String som for eksempel E: \ baeldung \ articles \ java består av tre navnelementer, dvs. baeldung, artikler, og java. Det høyeste elementet i katalogstrukturen vil være lokalisert ved indeks 0, i dette tilfellet baeldung.

Det laveste elementet i katalogstrukturen ligger i indeksen [n-1], hvor n er antall navnelementer i banen. Dette laveste elementet kalles filnavn uansett om det er en faktisk fil eller ikke:

@Test offentlig ugyldighet givenPath_whenRetrievesFileName_thenCorrect () {Path p = Paths.get ("/ articles / baeldung / logs"); Sti filnavn = p.getFileName (); assertEquals ("logs", fileName.toString ()); }

Metoder er tilgjengelige for å hente individuelle elementer etter indeks:

@Test offentlig ugyldighet givenPath_whenRetrievesNameByIndex_thenCorrect () {Path p = Paths.get ("/ articles / baeldung / logs"); Sti navn0 = getName (0); Sti navn1 = getName (1); Sti navn2 = getName (2); assertEquals ("artikler", name0.toString ()); assertEquals ("baeldung", name1.toString ()); assertEquals ("logger", name2.toString ()); }

eller en undersekvens av banen ved hjelp av disse indeksområdene:

@Test offentlig ugyldighet givenPath_whenCanRetrieveSubsequenceByIndex_thenCorrect () {Path p = Paths.get ("/ articles / baeldung / logs"); Sti subPath1 = p.subpath (0,1); Path subPath2 = p.subpath (0,2); assertEquals ("artikler", subPath1.toString ()); assertEquals ("artikler \ baeldung", subPath2.toString ()); assertEquals ("artikler \ baeldung \ logs", s.subpath (0, 3) .toString ()); assertEquals ("baeldung", s.subpath (1, 2) .toString ()); assertEquals ("baeldung \ logs", p.subpath (1, 3) .toString ()); assertEquals ("logger", s.subpath (2, 3) .toString ()); }

Hver bane er knyttet til en foreldresti eller null hvis stien ikke har noen foreldre. Overordnet til et baneobjekt består av banens rotkomponent, hvis noen, og hvert element i banen bortsett fra filnavnet. Som et eksempel, foreldrestien til / a / b / c er / a / b og den av /en er null:

@Test offentlig ugyldighet givenPath_whenRetrievesParent_thenCorrect () {Path p1 = Paths.get ("/ articles / baeldung / logs"); Sti p2 = Paths.get ("/ artikler / baeldung"); Sti p3 = Paths.get ("/ artikler"); Sti p4 = Paths.get ("/"); Baneforelder1 = p1.getParent (); Baneforelder2 = p2.getParent (); Sti foreldre3 = p3.getParent (); Baneforelder4 = p4.getParenth (); assertEquals ("\ artikler \ baeldung", parent1.toString ()); assertEquals ("\ articles", parent2.toString ()); assertEquals ("\", parent3.toString ()); assertEquals (null, parent4); }

Vi kan også få rotelementet til en bane:

@Test offentlig ugyldighet givenPath_whenRetrievesRoot_thenCorrect () {Path p1 = Paths.get ("/ articles / baeldung / logs"); Sti p2 = Paths.get ("c: / articles / baeldung / logs"); Sti root1 = p1.getRoot (); Sti root2 = p2.getRoot (); assertEquals ("\", root1.toString ()); assertEquals ("c: \", root2.toString ()); }

6. Normalisere en bane

Mange filsystemer bruker “.” notasjon for å betegne gjeldende katalog og “..” for å betegne foreldrekatalogen. Du kan ha en situasjon der en bane inneholder overflødig kataloginformasjon.

Tenk for eksempel på følgende banestrenger:

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

De løser alle til samme sted / baeldung / artikler. De to første har permitteringer mens den siste ikke har det.

Å normalisere en bane innebærer å fjerne permitteringer i den. De Sti. Normalisere () drift er gitt for dette formålet.

Dette eksemplet skal nå være selvforklarende:

@Test offentlig ugyldig givenPath_whenRemovesRedundancies_thenCorrect1 () {Path p = Paths.get ("/ home /./ baeldung / articles"); Banen cleanPath = p.normalize (); assertEquals ("\ home \ baeldung \ articles", cleanPath.toString ()); }

Denne også:

@Test offentlig ugyldighet givenPath_whenRemovesRedundancies_thenCorrect2 () {Path p = Paths.get ("/ home / baeldung /../ articles"); Banen cleanPath = p.normalize (); assertEquals ("\ hjem \ artikler", cleanPath.toString ()); }

7. Banekonvertering

Det er operasjoner for å konvertere en bane til et valgt presentasjonsformat. For å konvertere en bane til en streng som kan åpnes fra nettleseren, bruker vi toUri metode:

@Test offentlig ugyldig givenPath_whenConvertsToBrowseablePath_thenCorrect () {Path p = Paths.get ("/ home / baeldung / articles.html"); URI uri = p.toUri (); assertEquals ("file: /// E: /home/baeldung/articles.html", uri.toString ()); }

Vi kan også konvertere en sti til dens absolutte representasjon. De tilAbsolutePath metoden løser en sti mot en filkorts standardkatalog:

@Test offentlig ugyldig givenPath_whenConvertsToAbsolutePath_thenCorrect () {Path p = Paths.get ("/ home / baeldung / articles.html"); Sti absPath = p.toAbsolutePath (); assertEquals ("E: \ home \ baeldung \ articles.html", absPath.toString ()); }

Men når banen som skal løses oppdages å være absolutt, returnerer metoden den som den er:

@Test offentlig tomrom gittAbsolutePath_whenRetainsAsAbsolute_thenCorrect () {Path p = Paths.get ("E: \ home \ baeldung \ articles.html"); Sti absPath = p.toAbsolutePath (); assertEquals ("E: \ home \ baeldung \ articles.html", absPath.toString ()); }

Vi kan også konvertere hvilken som helst sti til den virkelige ekvivalenten ved å ringe toRealPath metode. Denne metoden prøver å løse banen ved å kartlegge elementene til faktiske kataloger og filer i filsystemet.

På tide å bruke variabelen vi opprettet i Oppsett seksjon som peker på innlogget brukerens hjemsted i filsystemet:

@Test offentlig ugyldig gittExistingPath_whenGetsRealPathToFile_thenCorrect () {Path p = Paths.get (HOME); Sti realPath = p.toRealPath (); assertEquals (HOME, realPath.toString ()); }

Ovennevnte test forteller oss ikke veldig mye om oppførselen til denne operasjonen. Det mest åpenbare resultatet er at hvis banen ikke eksisterer i filsystemet, vil operasjonen kaste en IO Unntak, Les videre.

På grunn av mangelen på en bedre måte å kjøre dette punktet hjem, er det bare å ta en titt på neste test, som prøver å konvertere en ikke-eksisterende bane til en reell bane:

@Test (forventet = NoSuchFileException.class) offentlig tomrom givenInExistentPath_whenFailsToConvert_thenCorrect () {Path p = Paths.get ("E: \ home \ baeldung \ articles.html"); p.toRealPath (); }

Testen lykkes når vi får en IO Unntak. Selve underklassen til IO Unntak som denne operasjonen kaster er NoSuchFileException.

8. Bli med på stier

Å bli med på to stier kan oppnås ved hjelp av Løse metode.

Enkelt sagt, vi kan ringe Løse metode på hvilken som helst Sti og pass i en delvis sti som argumentet. Den delvise stien er lagt til den opprinnelige stien:

@Test offentlig ugyldighet givenTwoPaths_whenJoinsAndResolves_thenCorrect () {Path p = Paths.get ("/ baeldung / articles"); Sti p2 = p.resolve ("java"); assertEquals ("\ baeldung \ articles \ java", p2.toString ()); }

Imidlertid når banestrengen gikk til Løse metoden er ikke en delvis sti; spesielt en absolutt sti, så returneres stien:

@Test offentlig ugyldighet gittAbsolutePath_whenResolutionRetainsIt_thenCorrect () {Path p = Paths.get ("/ baeldung / articles"); Sti p2 = p.resolve ("C: \ baeldung \ articles \ java"); assertEquals ("C: \ baeldung \ articles \ java", p2.toString ()); }

Det samme skjer med en hvilken som helst bane som har et rotelement. Banestrengen “Java” har ingen rotelement mens banestrengen “/ Java” har et rotelement. Derfor, når du passerer i en bane med et rotelement, returneres det som det er:

@Test offentlig ugyldighet givenPathWithRoot_whenResolutionRetainsIt_thenCorrect2 () {Path p = Paths.get ("/ baeldung / articles"); Sti p2 = p.resolve ("/ java"); assertEquals ("\ java", p2.toString ()); }

9. Relativiserende Stier

Begrepet relativiserende betyr ganske enkelt å skape en direkte sti mellom to kjente stier. For eksempel hvis vi har en katalog / baeldung og inne i den har vi to andre kataloger slik at / baeldung / forfattere og / baeldung / artikler er gyldige stier.

Veien til artikler i slekt med forfattere vil bli beskrevet som “Flytt ett nivå opp i kataloghierarkiet og deretter inn i artikelkatalogen” eller .. \ artikler:

@Test offentlig ugyldighet givenSiblingPaths_whenCreatesPathToOther_thenCorrect () {Path p1 = Paths.get ("articles"); Sti p2 = Paths.get ("forfattere"); Sti p1_rel_p2 = p1.relativiser (p2); Sti p2_rel_p1 = p2. Relativere (p1); assertEquals (".. \ forfattere", p1_rel_p2.toString ()); assertEquals (".. \ artikler", p2_rel_p1.toString ()); }

Forutsatt at vi flytter artikler katalog til forfattere mappe slik at de ikke lenger er søsken. Følgende relativiserende operasjoner innebærer å skape en vei mellom baeldung og artikler og vice versa:

@Test public void givenNonSiblingPaths_whenCreatesPathToOther_thenCorrect () {Path p1 = Paths.get ("/ baeldung"); Sti p2 = Paths.get ("/ baeldung / forfattere / artikler"); Sti p1_rel_p2 = p1.relativiser (p2); Sti p2_rel_p1 = p2. Relativere (p1); assertEquals ("forfattere \ artikler", p1_rel_p2.toString ()); assertEquals (".. \ ..", p2_rel_p1.toString ()); }

10. Sammenligning av stier

De Sti klassen har en intuitiv implementering av er lik metode som gjør at vi kan sammenligne to veier for likhet:

@Test offentlig ugyldighet givenTwoPaths_whenTestsEquality_thenCorrect () {Path p1 = Paths.get ("/ baeldung / articles"); Sti p2 = Paths.get ("/ baeldung / articles"); Sti p3 = Paths.get ("/ baeldung / forfattere"); assertTrue (p1.equals (p2)); assertFalse (p1.equals (p3)); }

Du kan også sjekke om en bane begynner med en gitt streng:

@Test offentlig ugyldighet givenPath_whenInspectsStart_thenCorrect () {Path p1 = Paths.get ("/ baeldung / articles"); assertTrue (p1.startsWith ("/ baeldung")); }

Eller slutter med en annen streng:

@Test offentlig ugyldig givenPath_whenInspectsEnd_thenCorrect () {Path p1 = Paths.get ("/ baeldung / articles"); assertTrue (p1.endsWith ("artikler")); }

11. Konklusjon

I denne artikkelen viste vi Path-operasjoner i det nye filsystemet API (NIO2) som ble sendt som en del av Java 7 og så de fleste av dem i aksjon.

Kodeprøvene som brukes i denne artikkelen finner du i artikkelens Github-prosjekt.


$config[zx-auto] not found$config[zx-overlay] not found