Uvod u Java NIO2 API datoteke

1. Pregled

U ovom ćemo se članku usredotočiti na nove I / O API-je u Java platformi - NIO2 - za osnovnu manipulaciju datotekama.

API-ji datoteka u NIO2 čine jedno od glavnih novih funkcionalnih područja Java platforme koja se isporučuje s Javom 7, posebno podskup novog API-ja datotečnog sustava uz Path API-je.

2. Postavljanje

Postavljanje vašeg projekta za upotrebu API-ja datoteka samo je pitanje uvoza:

import java.nio.file. *;

Budući da će se uzorci koda u ovom članku vjerojatno izvoditi u različitim okruženjima, uzmimo u obzir početni direktorij korisnika koji će vrijediti u svim operativnim sustavima:

privatni statički niz HOME = System.getProperty ("user.home");

The Datoteke razred je jedna od primarnih ulaznih točaka java.nio.file paket. Ova klasa nudi bogat skup API-ja za čitanje, pisanje i upravljanje datotekama i direktorijima. The Datoteke metode klase rade na primjerima Staza predmeta.

3. Provjera datoteke ili direktorija

Možemo imati Staza instanca koja predstavlja datoteku ili direktorij u datotečnom sustavu. Postoji li datoteka ili direktorij na koji upućuje postoji li ne, je li dostupan ili ne može se potvrditi operacijom datoteke.

Radi jednostavnosti, kad god koristimo taj izraz datoteka, mi ćemo se pozivati ​​i na datoteke i na direktorije, osim ako nije izričito navedeno drugačije.

Da bismo provjerili postoji li datoteka, koristimo postoji API:

@Test javna praznina givenExistentPath_whenConfirmsFileExists_thenCorrect () {Path p = Paths.get (HOME); assertTrue (Files.exists (p)); }

Da bismo provjerili postoji li datoteka, koristimo nePostoji API:

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

Također možemo provjeriti je li datoteka uobičajena datoteka poput myfile.txt ili je samo direktorij, koristimo isRegularFile API:

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

Postoje i statičke metode za provjeru dozvola za datoteke. Da bismo provjerili je li datoteka čitljiva, koristimo isReadable API:

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

Da bismo provjerili može li se na nju pisati, koristimo isWritable API:

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

Slično tome, da biste provjerili je li izvršan:

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

Kada imamo dvije staze, možemo provjeriti upućuju li obje na istu datoteku u temeljnom datotečnom sustavu:

@Test javna praznina givenSameFilePaths_whenConfirmsIsSame_thenCorrect () {Path p1 = Paths.get (HOME); Put p2 = Putovi.get (KUĆA); assertTrue (Files.isSameFile (p1, p2)); }

4. Stvaranje datoteka

API datotečnog sustava pruža operacije u jednom redu za stvaranje datoteka. Da bismo stvorili redovitu datoteku, koristimo createFile API i proslijedite ga a Staza objekt koji predstavlja datoteku koju želimo stvoriti.

Svi elementi imena u stazi moraju postojati, osim imena datoteke, u protivnom ćemo dobiti IOException:

@Test javna praznina givenFilePath_whenCreatesNewFile_thenCorrect () {String fileName = "myfile_" + UUID.randomUUID (). ToString () + ".txt"; Put p = Paths.get (HOME + "/" + FileName); assertFalse (Files.exists (p)); Files.createFile (p); assertTrue (Files.exists (p)); }

U gornjem testu, kada prvi put provjerimo put, on ne postoji, a zatim nakon createFile utvrđeno je da postoji.

Da bismo stvorili direktorij, koristimo createDirectory API:

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

Ova operacija zahtijeva da svi elementi imena na putu postoje, ako ne, dobit ćemo i IOException:

@Test (očekuje se = NoSuchFileException.class) javna praznina givenDirPath_whenFailsToCreateRecursively_thenCorrect () {String dirName = "myDir_" + UUID.randomUUID (). ToString () + "/ subdir"; Put p = Paths.get (HOME + "/" + dirName); assertFalse (Files.exists (p)); Files.createDirectory (p); }

Međutim, ako želimo stvoriti hijerarhiju direktorija jednim pozivom, koristimo createDirectories metoda. Za razliku od prethodne operacije, kada naiđe na nedostajuće elemente imena u putanji, ne baca znak IOException, stvara ih rekurzivno vodeći do posljednjeg elementa:

@Test javna praznina givenDirPath_whenCreatesRecursively_thenCorrect () {Direktor puta = Paths.get (HOME + "/ myDir_" + UUID.randomUUID (). ToString ()); Subdir putanje = dir.resolve ("subdir"); assertFalse (Files.exists (dir)); assertFalse (Files.exists (subdir)); Files.createDirectories (poddir); assertTrue (Files.exists (dir)); assertTrue (Files.exists (subdir)); }

5. Stvaranje privremenih datoteka

Mnoge aplikacije stvaraju trag privremenih datoteka u datotečnom sustavu dok se izvode. Kao rezultat toga, većina datotečnih sustava ima namjenski direktorij za pohranu privremenih datoteka koje generiraju takve aplikacije.

Novi API datotečnog sustava pruža posebne radnje u tu svrhu. The createTempFile API izvodi ovu operaciju. Potreban je objekt staze, prefiks datoteke i sufiks datoteke:

@Test javna praznina givenFilePath_whenCreatesTempFile_thenCorrect () {Prefiks niza = "log_"; Sufiks niza = ".txt"; Path p = Paths.get (HOME + "/"); Files.createTempFile (p, prefiks, sufiks); assertTrue (Files.exists (p)); }

Ti su parametri dovoljni za zahtjeve kojima je potrebna ova operacija. Međutim, ako trebate navesti određene atribute datoteke, postoji četvrti parametar varijable argument.

Gornji test stvara privremenu datoteku u DOM direktorij, prethodno čekajući i dodajući ponuđeni niz prefiksa i sufiksa. Završit ćemo s nazivom datoteke poput log_8821081429012075286.txt. Dugi numerički niz generira se sustavom.

Međutim, ako ne navedemo prefiks i sufiks, tada će naziv datoteke sadržavati samo dugi numerički niz i zadani .tmp produžetak:

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

Gornja operacija stvara datoteku s imenom poput 8600179353689423985.tmp.

Konačno, ako ne pružimo ni putanju, ni prefiks ni sufiks, tada će operacija u cijelosti koristiti zadane vrijednosti. Zadano mjesto stvorene datoteke bit će direktorij privremene datoteke koji pruža datotečni sustav:

@Test public void givenNoFilePath_whenCreatesTempFileInTempDir_thenCorrect () {Path p = Files.createTempFile (null, null); assertTrue (Files.exists (p)); }

Na Windowsima će ovo zadati nešto poput C: \ Users \ user \ AppData \ Local \ Temp \ 6100927974988978748.tmp.

Sve gore navedene radnje mogu se prilagoditi stvaranju direktorija, a ne uobičajenih datoteka pomoću createTempDirectory umjesto createTempFile.

6. Brisanje datoteke

Za brisanje datoteke koristimo izbrisati API. Radi jasnoće, sljedeći test prvo osigurava da datoteka već ne postoji, zatim je kreira i potvrđuje da sada postoji te na kraju briše i potvrđuje da više ne postoji:

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

Međutim, ako datoteka ne postoji u datotečnom sustavu, operacija brisanja neće uspjeti s datotekom IOException:

@Test (očekuje se = NoSuchFileException.class) javna praznina givenInexistentFile_whenDeleteFails_thenCorrect () {Path p = Paths.get (HOME + "/inexistentFile.txt"); assertFalse (Files.exists (p)); Files.delete (p); }

Ovaj scenarij možemo izbjeći pomoću deleteIfExists koji tiho propadnu u slučaju da datoteka ne postoji. To je važno kada ovu operaciju izvodi više niti, a mi ne želimo poruku o neuspjehu samo zato što je nit izveo operaciju ranije od trenutne niti koja nije uspjela:

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

Kada se radi s direktorijima, a ne s uobičajenim datotekama, trebali bismo imati na umu da operacija brisanja prema zadanim postavkama ne radi rekurzivno. Dakle, ako direktorij nije prazan, neće uspjeti s IOException:

@Test (očekuje se = DirectoryNotEmptyException.class) javna praznina givenPath_whenFailsToDeleteNonEmptyDir_thenCorrect () {Dir putanja = Paths.get (HOME + "/ emptyDir" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir); assertTrue (Files.exists (dir)); Datoteka puta = dir.resolve ("file.txt"); Files.createFile (datoteka); Files.delete (dir); assertTrue (Files.exists (dir)); }

7. Kopiranje datoteka

Možete kopirati datoteku ili direktorij pomoću kopirati API:

@Test javna praznina givenFilePath_whenCopiesToNewLocation_thenCorrect () {dir1 putanje = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Dir2 putanje = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Put datoteka1 = dir1.resolve ("filetocopy.txt"); Put datoteka2 = dir2.resolve ("filetocopy.txt"); Files.createFile (datoteka1); assertTrue (Files.exists (datoteka1)); assertFalse (Files.exists (datoteka2)); Files.copy (datoteka1, datoteka2); assertTrue (Files.exists (datoteka2)); }

Kopija ne uspije ako postoji ciljana datoteka, osim ako ZAMJENA_POSTOJEĆE navedena je opcija:

@Test (očekuje se = FileAlreadyExistsException.class) javna praznina givenPath_whenCopyFailsDueToExistingFile_thenCorrect () {Path dir1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Dir2 putanje = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Put datoteka1 = dir1.resolve ("filetocopy.txt"); Put datoteka2 = dir2.resolve ("filetocopy.txt"); Files.createFile (datoteka1); Files.createFile (datoteka2); assertTrue (Files.exists (datoteka1)); assertTrue (Files.exists (datoteka2)); Files.copy (datoteka1, datoteka2); Files.copy (datoteka1, datoteka2, StandardCopyOption.REPLACE_EXISTING); }

Međutim, prilikom kopiranja direktorija, sadržaj se ne kopira rekurzivno. To znači da ako / baeldung sadrži /articles.db i /authors.db datoteke, kopiranje / baeldung na novo mjesto stvorit će prazan direktorij.

8. Premještanje datoteka

Datoteku ili direktorij možete premjestiti pomoću potez API. U većini je slučajeva sličan kopirati operacija. Ako je postupak kopiranja analogan a Kopiranje i lijepljenje rad u sustavima temeljenim na GUI-u potez je analogno a izreži i zalijepi operacija:

@Test javna praznina givenFilePath_whenMovesToNewLocation_thenCorrect () {dir1 putanje = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Dir2 putanje = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Put datoteka1 = dir1.resolve ("filetocopy.txt"); Put datoteka2 = dir2.resolve ("filetocopy.txt"); Files.createFile (datoteka1); assertTrue (Files.exists (datoteka1)); assertFalse (Files.exists (datoteka2)); Files.move (datoteka1, datoteka2); assertTrue (Files.exists (datoteka2)); assertFalse (Files.exists (datoteka1)); }

The potez operacija ne uspije ako ciljna datoteka postoji osim ako ZAMJENA_POSTOJEĆE opcija je navedena baš kao što smo učinili s kopirati operacija:

@Test (očekuje se = FileAlreadyExistsException.class) javna praznina givenFilePath_whenMoveFailsDueToExistingFile_thenCorrect () {Path dir1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Dir2 putanje = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Put datoteka1 = dir1.resolve ("filetocopy.txt"); Put datoteka2 = dir2.resolve ("filetocopy.txt"); Files.createFile (datoteka1); Files.createFile (datoteka2); assertTrue (Files.exists (datoteka1)); assertTrue (Files.exists (datoteka2)); Files.move (datoteka1, datoteka2); Files.move (datoteka1, datoteka2, StandardCopyOption.REPLACE_EXISTING); assertTrue (Files.exists (datoteka2)); assertFalse (Files.exists (datoteka1)); }

9. Zaključak

U ovom smo članku saznali o API-jevima datoteka u novom API-ju datotečnog sustava (NIO2) koji je isporučen kao dio Jave 7 i vidio je većinu važnih operacija datoteka na djelu.

Uzorci koda korišteni u ovom članku mogu se naći u članku u projektu Github.