Introduksjon til Java NIO2 File API

1. Oversikt

I denne artikkelen skal vi fokusere på de nye I / O API-ene i Java-plattformen - NIO2 - for å gjøre grunnleggende filmanipulering.

Fil-API-er i NIO2 utgjør et av de viktigste nye funksjonelle områdene til Java-plattformen som ble levert med Java 7, spesielt et delsett av det nye filsystem-API-et sammen med Path-APIer.

2. Oppsett

Å sette opp prosjektet ditt for å bruke File APIs er bare et spørsmål om å importere dette:

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, som vil være gyldig i alle operativsystemer:

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

De Filer klasse er et av de viktigste inngangspunktene til java.nio.file pakke. Denne klassen tilbyr et rikt sett med API-er for lesing, skriving og manipulering av filer og kataloger. De Filer klassemetoder fungerer på forekomster av Sti gjenstander.

3. Kontrollere en fil eller katalog

Vi kan ha en Sti forekomst som representerer en fil eller en katalog på filsystemet. Enten filen eller katalogen den peker på eksisterer eller ikke, er tilgjengelig eller ikke, kan bekreftes av en filoperasjon.

For enkelhets skyld, når vi bruker begrepet fil, vil vi henvise til både filer og kataloger med mindre annet er uttrykkelig angitt.

For å sjekke om en fil eksisterer, bruker vi eksisterer API:

@Test offentlig ugyldig gittExistentPath_whenConfirmsFileExists_thenCorrect () {Path p = Paths.get (HOME); assertTrue (Files.exists (p)); }

For å kontrollere at en fil ikke eksisterer, bruker vi notExists API:

@Test offentlig ugyldighet gittNonexistentPath_whenConfirmsFileNotExists_thenCorrect () {Path p = Paths.get (HOME + "/inexistent_file.txt"); assertTrue (Files.notExists (p)); }

Vi kan også sjekke om en fil er en vanlig fil som myfile.txt eller er bare en katalog, bruker vi isRegularFile API:

@Test offentlig ugyldig givenDirPath_whenConfirmsNotRegularFile_thenCorrect () {Path p = Paths.get (HOME); assertFalse (Files.isRegularFile (p)); }

Det er også statiske metoder for å se etter filtillatelser. For å sjekke om en fil er lesbar, bruker vi er lesbar API:

@Test offentlig ugyldig gittExistentDirPath_whenConfirmsReadable_thenCorrect () {Path p = Paths.get (HOME); assertTrue (Files.isReadable (p)); }

For å sjekke om det er skrivbart, bruker vi er skrivbar API:

@Test offentlig ugyldig gittExistentDirPath_whenConfirmsWritable_thenCorrect () {Path p = Paths.get (HOME); assertTrue (Files.isWritable (p)); }

På samme måte for å sjekke om den er kjørbar:

@Test offentlig ugyldig gittExistentDirPath_whenConfirmsExecutable_thenCorrect () {Path p = Paths.get (HOME); assertTrue (Files.isExecutable (p)); }

Når vi har to baner, kan vi sjekke om de begge peker på den samme filen på det underliggende filsystemet:

@Test offentlig ugyldighet givenSameFilePaths_whenConfirmsIsSame_thenCorrect () {Path p1 = Paths.get (HOME); Sti p2 = Paths.get (HJEM); assertTrue (Files.isSameFile (p1, p2)); }

4. Opprette filer

Filsystem-API-en gir enkel linjeoperasjoner for å lage filer. For å lage en vanlig fil bruker vi createFile API og overfør til den a Sti objekt som representerer filen vi vil lage.

Alle navnelementene i banen må eksistere, bortsett fra filnavnet, ellers får vi en IO-unntak:

@Test offentlig ugyldig givenFilePath_whenCreatesNewFile_thenCorrect () {String fileName = "myfile_" + UUID.randomUUID (). ToString () + ".txt"; Sti p = Paths.get (HOME + "/" + filnavn); assertFalse (Files.exists (p)); Files.createFile (p); assertTrue (Files.exists (p)); }

I testen ovenfor, når vi først sjekker banen, er den ikke eksisterende, deretter etter createFile operasjon, er det funnet å eksistere.

For å lage en katalog bruker vi createDirectory API:

@Test offentlig ugyldig givenDirPath_whenCreatesNewDir_thenCorrect () {String dirName = "myDir_" + UUID.randomUUID (). ToString (); Sti p = Paths.get (HOME + "/" + dirName); assertFalse (Files.exists (p)); Files.createDirectory (p); assertTrue (Files.exists (p)); assertFalse (Files.isRegularFile (p)); assertTrue (Files.isDirectory (p)); }

Denne operasjonen krever at alle navnelementene i banen eksisterer, hvis ikke, får vi også en IO Unntak:

@Test (forventet = NoSuchFileException.class) offentlig ugyldig givenDirPath_whenFailsToCreateRecursively_thenCorrect () {String dirName = "myDir_" + UUID.randomUUID (). ToString () + "/ subdir"; Sti p = Paths.get (HOME + "/" + dirName); assertFalse (Files.exists (p)); Files.createDirectory (p); }

Imidlertid, hvis vi ønsker å lage et hierarki med kataloger med en enkelt samtale, bruker vi createDirectories metode. I motsetning til den forrige operasjonen, når den støter på manglende navnelementer i banen, kaster den ikke en IO Unntak, det skaper dem rekursivt fram til det siste elementet:

@Test offentlig ugyldig givenDirPath_whenCreatesRecursively_thenCorrect () {Path dir = Paths.get (HOME + "/ myDir_" + UUID.randomUUID (). ToString ()); Path subdir = dir.resolve ("subdir"); assertFalse (Files.exists (dir)); assertFalse (Files.exists (subdir)); Files.createDirectories (undermappe); assertTrue (Files.exists (dir)); assertTrue (Files.exists (subdir)); }

5. Opprette midlertidige filer

Mange applikasjoner oppretter et spor av midlertidige filer i filsystemet mens de kjører. Som et resultat har de fleste filsystemer en egen katalog for å lagre midlertidige filer generert av slike applikasjoner.

Det nye filsystemet API gir spesifikke operasjoner for dette formålet. De createTempFile API utfører denne operasjonen. Det tar et baneobjekt, et filprefiks og et filsuffiks:

@Test offentlig ugyldig givenFilePath_whenCreatesTempFile_thenCorrect () {String prefix = "log_"; Strengssuffiks = ".txt"; Sti p = Paths.get (HOME + "/"); Files.createTempFile (p, prefiks, suffiks); assertTrue (Files.exists (p)); }

Disse parametrene er tilstrekkelig for krav som trenger denne operasjonen. Imidlertid, hvis du trenger å spesifisere spesifikke attributter for filen, er det en fjerde parameter for variable argumenter.

Ovennevnte test oppretter en midlertidig fil i HJEM katalog, forhåndsventende og tilføying av henholdsvis prefiks og suffiksstrenger. Vi vil ende opp med et filnavn som log_8821081429012075286.txt. Den lange numeriske strengen genereres av systemet.

Men hvis vi ikke gir et prefiks og et suffiks, vil filnavnet bare omfatte den lange numeriske strengen og en standard .tmp Utvidelse:

@Test offentlig ugyldighet givenPath_whenCreatesTempFileWithDefaults_thenCorrect () {Path p = Paths.get (HOME + "/"); Files.createTempFile (p, null, null); assertTrue (Files.exists (p)); }

Ovennevnte operasjon oppretter en fil med et navn som 8600179353689423985.tmp.

Til slutt, hvis vi verken gir sti, prefiks eller suffiks, vil operasjonen bruke standardinnstillinger hele veien. Standardplasseringen til den opprettede filen vil være filsystemet som er gitt midlertidig filkatalog:

@Test offentlig ugyldighet gittNoFilePath_whenCreatesTempFileInTempDir_thenCorrect () {Path p = Files.createTempFile (null, null); assertTrue (Files.exists (p)); }

På windows vil dette som standard være noe C: \ Brukere \ bruker \ AppData \ Lokal \ Temp \ 6100927974988978748.tmp.

Alle operasjonene ovenfor kan tilpasses for å opprette kataloger i stedet for vanlige filer ved hjelp av createTempDirectory i stedet for createTempFile.

6. Slette en fil

For å slette en fil bruker vi slett API. For å oppnå klarhet sikrer følgende test først at filen ikke allerede eksisterer, deretter oppretter den og bekrefter at den nå eksisterer, og til slutt sletter den og bekrefter at den ikke lenger eksisterer:

@Test offentlig ugyldighet givenPath_whenDeletes_thenCorrect () {Path p = Paths.get (HOME + "/fileToDelete.txt"); assertFalse (Files.exists (p)); Files.createFile (p); assertTrue (Files.exists (p)); Files.delete (p); assertFalse (Files.exists (p)); }

Imidlertid, hvis en fil ikke finnes i filsystemet, vil slettingen mislykkes med en IO Unntak:

@Test (forventet = NoSuchFileException.class) offentlig ugyldig givenInexistentFile_whenDeleteFails_thenCorrect () {Path p = Paths.get (HOME + "/inexistentFile.txt"); assertFalse (Files.exists (p)); Files.delete (p); }

Vi kan unngå dette scenariet ved å bruke deleteIfExists som mislykkes stille hvis filen ikke eksisterer. Dette er viktig når flere tråder utfører denne operasjonen, og vi ikke vil ha en feilmelding bare fordi en tråd utførte operasjonen tidligere enn den gjeldende tråden som mislyktes:

@Test offentlig ugyldig givenInexistentFile_whenDeleteIfExistsWorks_thenCorrect () {Path p = Paths.get (HOME + "/inexistentFile.txt"); assertFalse (Files.exists (p)); Files.deleteIfExists (p); }

Når du arbeider med kataloger og ikke vanlige filer, bør vi huske at sletteoperasjonen ikke fungerer rekursivt som standard. Så hvis en katalog ikke er tom, vil den mislykkes med en IO Unntak:

@Test (forventet = DirectoryNotEmptyException.class) offentlig ugyldig givenPath_whenFailsToDeleteNonEmptyDir_thenCorrect () {Path dir = Paths.get (HOME + "/ emptyDir" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir); assertTrue (Files.exists (dir)); Sti-fil = dir.resolve ("file.txt"); Files.createFile (fil); Files.delete (dir); assertTrue (Files.exists (dir)); }

7. Kopiere filer

Du kan kopiere en fil eller katalog ved å bruke kopiere API:

@Test offentlig ugyldig givenFilePath_whenCopiesToNewLocation_thenCorrect () {Path dir1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Sti dir2 = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Sti fil1 = dir1.resolve ("filetocopy.txt"); Banefil2 = dir2.resolve ("filetocopy.txt"); Files.createFile (file1); assertTrue (Files.exists (file1)); assertFalse (Files.exists (file2)); Files.copy (file1, file2); assertTrue (Files.exists (file2)); }

Kopien mislykkes hvis målfilen eksisterer med mindre REPLACE_EXISTING alternativet er spesifisert:

@Test (forventet = FileAlreadyExistsException.class) offentlig ugyldig givenPath_whenCopyFailsDueToExistingFile_thenCorrect () {Path dir1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Sti dir2 = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Sti fil1 = dir1.resolve ("filetocopy.txt"); Banefil2 = dir2.resolve ("filetocopy.txt"); Files.createFile (file1); Files.createFile (file2); assertTrue (Files.exists (file1)); assertTrue (Files.exists (file2)); Files.copy (file1, file2); Files.copy (file1, file2, StandardCopyOption.REPLACE_EXISTING); }

Imidlertid kopieres ikke innholdet rekursivt når du kopierer kataloger. Dette betyr at hvis / baeldung inneholder /artikler.db og /autorer.db filer, kopiering / baeldung til et nytt sted vil opprette en tom katalog.

8. Flytte filer

Du kan flytte en fil eller katalog ved å bruke bevege seg API. Det ligner på de fleste måter kopiere operasjon. Hvis kopieringen er analog med a kopiere og lime inn drift i GUI-baserte systemer, da bevege seg er analog med a klipp og lim operasjon:

@Test offentlig tomrom givenFilePath_whenMovesToNewLocation_thenCorrect () {Path dir1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Sti dir2 = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Sti fil1 = dir1.resolve ("filetocopy.txt"); Banefil2 = dir2.resolve ("filetocopy.txt"); Files.createFile (file1); assertTrue (Files.exists (file1)); assertFalse (Files.exists (file2)); Files.move (file1, file2); assertTrue (Files.exists (file2)); assertFalse (Files.exists (file1)); }

De bevege seg operasjonen mislykkes hvis målfilen eksisterer med mindre REPLACE_EXISTING alternativet er spesifisert akkurat som vi gjorde med kopiere operasjon:

@Test (forventet = FileAlreadyExistsException.class) offentlig ugyldig givenFilePath_whenMoveFailsDueToExistingFile_thenCorrect () {Path dir1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Sti dir2 = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Sti fil1 = dir1.resolve ("filetocopy.txt"); Banefil2 = dir2.resolve ("filetocopy.txt"); Files.createFile (file1); Files.createFile (file2); assertTrue (Files.exists (file1)); assertTrue (Files.exists (file2)); Files.move (file1, file2); Files.move (file1, file2, StandardCopyOption.REPLACE_EXISTING); assertTrue (Files.exists (file2)); assertFalse (Files.exists (file1)); }

9. Konklusjon

I denne artikkelen lærte vi om fil-API-er i det nye filsystemet API (NIO2) som ble sendt som en del av Java 7 og så de fleste av de viktige filoperasjonene 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