Introduktion til Java NIO2 File API

1. Oversigt

I denne artikel vil vi fokusere på de nye I / O API'er i Java-platformen - NIO2 - for at udføre grundlæggende filmanipulation.

Fil-API'er i NIO2 udgør et af de store nye funktionelle områder af Java-platformen, der blev leveret med Java 7, specifikt en delmængde af det nye filsystem API sammen med sti-API'er.

2. Opsætning

Opsætning af dit projekt til at bruge File API'er er bare et spørgsmål om at foretage denne import:

import java.nio.file. *;

Da kodeeksemplerne i denne artikel sandsynligvis kører i forskellige miljøer, lad os få fat i brugerens hjemmemappe, som vil være gyldig på tværs af alle operativsystemer:

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

Det Filer klasse er et af de primære indgangspunkter for java.nio.file pakke. Denne klasse tilbyder et rigt sæt API'er til læsning, skrivning og manipulation af filer og mapper. Det Filer klassemetoder fungerer i tilfælde af Sti genstande.

3. Kontrol af en fil eller et bibliotek

Vi kan have en Sti forekomst, der repræsenterer en fil eller et bibliotek på filsystemet. Uanset om den fil eller det katalog, det peger på, eksisterer eller ej, er tilgængelig eller ej, kan det bekræftes af en filhandling.

Af hensyn til enkelheden, når vi bruger udtrykket fil, vi vil henvise til både filer og kataloger, medmindre andet udtrykkeligt er angivet.

For at kontrollere, om der findes en fil, bruger vi eksisterer API:

@Test offentlig ugyldighed givenExistentPath_whenConfirmsFileExists_thenCorrect () {Sti p = Paths.get (HJEM); assertTrue (Files.exists (p)); }

For at kontrollere, at en fil ikke findes, bruger vi notExists API:

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

Vi kan også kontrollere, om en fil er en almindelig fil som myfile.txt eller er bare et bibliotek, bruger vi isRegularFile API:

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

Der er også statiske metoder til at kontrollere for filtilladelser. For at kontrollere, om en fil er læsbar, bruger vi er læsbar API:

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

For at kontrollere, om det er skrivbart, bruger vi er skrivelig API:

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

Tilsvarende for at kontrollere, om den er eksekverbar:

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

Når vi har to stier, kan vi kontrollere, om de begge peger på den samme fil på det underliggende filsystem:

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

4. Oprettelse af filer

Filsystemets API giver enkeltlinjeoperationer til oprettelse af filer. For at oprette en almindelig fil bruger vi createFile API og videregive det til en Sti objekt, der repræsenterer den fil, vi vil oprette.

Alle navnelementerne i stien skal eksistere bortset fra filnavnet, ellers får vi en IO-undtagelse:

@Test offentlig ugyldighed 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 ovenstående test, når vi først kontrollerer stien, er den ikke-eksisterende, derefter efter createFile operation, det findes at eksistere.

For at oprette et bibliotek bruger vi createDirectory API:

@Test offentlig ugyldighed 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 operation kræver, at alle navnelementer i stien findes, hvis ikke, får vi også en IOUndtagelse:

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

Men hvis vi ønsker at oprette et hierarki af mapper med et enkelt opkald, bruger vi createDirectories metode. I modsætning til den forrige operation, når den støder på manglende navnelementer i stien, kaster den ikke et IOUndtagelse, det skaber dem rekursivt, der fører op til det sidste element:

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

5. Oprettelse af midlertidige filer

Mange applikationer opretter et spor af midlertidige filer i filsystemet, når de kører. Som et resultat har de fleste filsystemer et dedikeret bibliotek til lagring af midlertidige filer genereret af sådanne applikationer.

Det nye filsystem API giver specifikke operationer til dette formål. Det createTempFile API udfører denne handling. Det tager et stiobjekt, et filpræfiks og et fil suffiks:

@Test offentlig ugyldighed givenFilePath_whenCreatesTempFile_thenCorrect () {String prefix = "log_"; Strengsuffiks = ".txt"; Sti p = Paths.get (HOME + "/"); Files.createTempFile (p, præfiks, suffiks); assertTrue (Files.exists (p)); }

Disse parametre er tilstrækkelige til krav, der har brug for denne operation. Men hvis du har brug for at specificere specifikke attributter for filen, er der en fjerde parameter for variable argumenter.

Ovenstående test opretter en midlertidig fil i HJEM bibliotek, forudgående og tilføjelse af henholdsvis den medfølgende præfiks og suffiksstreng. Vi ender med et filnavn som log_8821081429012075286.txt. Den lange numeriske streng genereres af systemet.

Men hvis vi ikke giver et præfiks og et suffiks, så inkluderer filnavnet kun den lange numeriske streng og en standard .tmp udvidelse:

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

Ovenstående handling opretter en fil med et navn som 8600179353689423985.tmp.

Endelig, hvis vi hverken angiver sti, præfiks eller suffiks, vil operationen bruge standardindstillinger overalt. Den oprettede fils standardplacering er det filsystem, der leveres midlertidig filmappe:

@Test offentlig ugyldighed givenNoFilePath_whenCreatesTempFileInTempDir_thenCorrect () {Sti p = Files.createTempFile (null, null); assertTrue (Files.exists (p)); }

På windows vil dette som standard være noget lignende C: \ Brugere \ bruger \ AppData \ Lokal \ Temp \ 6100927974988978748.tmp.

Alle ovenstående operationer kan tilpasses til at oprette mapper i stedet for almindelige filer ved hjælp af createTempDirectory i stedet for createTempFile.

6. Sletning af en fil

For at slette en fil bruger vi slet API. Af hensyn til klarheden sikrer følgende test først, at filen ikke allerede eksisterer, opretter den derefter og bekræfter, at den nu eksisterer, og til sidst slettes den og bekræfter, at den ikke længere eksisterer:

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

Hvis der imidlertid ikke findes en fil i filsystemet, mislykkes sletningen med et IOUndtagelse:

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

Vi kan undgå dette scenario ved at bruge deleteIfExists som fejler lydløst, hvis filen ikke findes. Dette er vigtigt, når flere tråde udfører denne operation, og vi ikke ønsker en fejlmeddelelse, simpelthen fordi en tråd udførte operationen tidligere end den aktuelle tråd, der har fejlet:

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

Når vi beskæftiger os med mapper og ikke almindelige filer, skal vi huske, at sletningen ikke fungerer rekursivt som standard. Så hvis en mappe ikke er tom, vil den mislykkes med en IOUndtagelse:

@Test (forventet = DirectoryNotEmptyException.class) offentlig ugyldighed givenPath_whenFailsToDeleteNonEmptyDir_thenCorrect () {Sti 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. Kopiering af filer

Du kan kopiere en fil eller et bibliotek ved hjælp af kopi API:

@Test offentlig ugyldighed 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"); Sti fil2 = 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 findes, medmindre REPLACE_EXISTING mulighed er angivet:

@Test (forventet = FileAlreadyExistsException.class) offentlig ugyldighed givenPath_whenCopyFailsDueToExistingFile_thenCorrect () {Sti 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"); Sti fil2 = 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); }

Ved kopiering af mapper kopieres indholdet imidlertid ikke rekursivt. Dette betyder, at hvis / baeldung indeholder /artikler.db og /autorer.db filer, kopiering / baeldung til en ny placering opretter en tom mappe.

8. Flytning af filer

Du kan flytte en fil eller et bibliotek ved hjælp af bevæge sig API. Det ligner på de fleste måder kopi operation. Hvis kopieringen er analog med a kopiere og indsætte drift i GUI-baserede systemer bevæge sig er analog med a klip og sæt ind operation:

@Test offentlig ugyldighed 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"); Sti fil2 = 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)); }

Det bevæge sig operation mislykkes, hvis målfilen findes, medmindre REPLACE_EXISTING option er angivet ligesom vi gjorde med kopi operation:

@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"); Sti fil2 = 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. Konklusion

I denne artikel lærte vi om fil-API'er i det nye filsystem API (NIO2), der blev sendt som en del af Java 7 og så de fleste af de vigtige filhandlinger i aktion.

Kodeprøverne, der bruges i denne artikel, kan findes i artiklens Github-projekt.


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