Bevezetés a Java NIO2 File API-ba

1. Áttekintés

Ebben a cikkben a Java Platform új I / O API-jára fogunk összpontosítani - NIO2 - alapvető fájlkezelés.

A NIO2 fájl API-k alkotják a Java 7 egyik legfontosabb új funkcionális területét, amelyet a Java 7-el együtt szállítottak, nevezetesen az új fájlrendszer API részhalmazát a Path API-k mellett.

2. Beállítás

A projekt beállítása a File API-k használatára csak az importálás kérdése:

import java.nio.file. *;

Mivel az ebben a cikkben szereplő kódminták valószínűleg különböző környezetekben fognak futni, szerezzünk egy kezelési lehetőséget a felhasználó saját könyvtárában, amely minden operációs rendszerre érvényes lesz:

privát statikus karakterlánc HOME = System.getProperty ("user.home");

A Fájlok osztály az egyik elsődleges belépési pont a java.nio.file csomag. Ez az osztály gazdag API-kat kínál a fájlok és könyvtárak olvasására, írására és kezelésére. A Fájlok osztályos módszerek működnek az Pálya tárgyakat.

3. Fájl vagy könyvtár ellenőrzése

Van egy Pálya egy fájlt vagy könyvtárat reprezentáló példány a fájlrendszerben. Függetlenül attól, hogy létezik-e az a fájl vagy könyvtár, amelyre mutat, vagy sem, egy fájlművelettel meg lehet erősíteni.

Az egyszerűség kedvéért, valahányszor ezt a kifejezést használjuk fájl, mind a fájlokra, mind a könyvtárakra hivatkozunk, hacsak kifejezetten másként nem jelezzük.

A fájl létezésének ellenőrzéséhez a létezik API:

@Test public void givenExistentPath_whenConfirmsFileExists_thenCorrect () {Path p = Paths.get (HOME); assertTrue (Fájlok.létezik (p)); }

A fájl nem létezésének ellenőrzéséhez a nem létezik API:

@Test public void givenNonexistentPath_whenConfirmsFileNotExists_thenCorrect () {Path p = Paths.get (HOME + "/inexistent_file.txt"); assertTrue (Fájlok.notExists (p)); }

Azt is ellenőrizhetjük, hogy egy fájl szokásos fájl-e myfile.txt vagy csak könyvtár, akkor a isRegularFile API:

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

A fájlengedélyek ellenőrzésére statikus módszerek is léteznek. Annak ellenőrzésére, hogy egy fájl olvasható-e, a isolvasható API:

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

Annak ellenőrzésére, hogy írható-e, a írható API:

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

Hasonlóképpen ellenőrizze, hogy végrehajtható-e:

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

Ha két útvonalunk van, ellenőrizhetjük, hogy mindkettő ugyanarra a fájlra mutat-e az alapul szolgáló fájlrendszeren:

@Test public void givenSameFilePaths_whenConfirmsIsSame_thenCorrect () {Path p1 = Paths.get (HOME); P2 útvonal = Paths.get (HOME); assertTrue (Files.isSameFile (p1, p2)); }

4. Fájlok létrehozása

A fájlrendszer API egysoros műveleteket biztosít a fájlok létrehozásához. Rendes fájl létrehozásához a createFile API és adja át a Pálya a létrehozni kívánt fájlt képviselő objektum.

Az útvonalban található összes névelemnek léteznie kell, a fájlnéven kívül, különben egy IOException:

@Test public void givenFilePath_whenCreatesNewFile_thenCorrect () {String fileName = "myfile_" + UUID.randomUUID (). ToString () + ".txt"; Path p = Paths.get (HOME + "/" + fájlnév); assertFalse (Fájlok.létezik (p)); Files.createFile (p); assertTrue (Fájlok.létezik (p)); }

A fenti tesztben, amikor először ellenőrizzük az útvonalat, akkor az nem létezik, majd a createFile művelet létezik.

Könyvtár létrehozásához a createDirectory API:

@Test public void givenDirPath_whenCreatesNewDir_thenCorrect () {String dirName = "myDir_" + UUID.randomUUID (). ToString (); Path p = Paths.get (HOME + "/" + dirName); assertFalse (Fájlok.létezik (p)); Files.createDirectory (p); assertTrue (Fájlok.létezik (p)); assertFalse (Files.isRegularFile (p)); assertTrue (Fájlok.isDirectory (p)); }

Ehhez a művelethez meg kell adni az útvonalban található összes névelemet, ha nem, akkor kapunk egy IOException:

@Test (várható = NoSuchFileException.class) public void givenDirPath_whenFailsToCreateRecursively_thenCorrect () {String dirName = "myDir_" + UUID.randomUUID (). ToString () + "/ alkönyvtár"; Path p = Paths.get (HOME + "/" + dirName); assertFalse (Fájlok.létezik (p)); Files.createDirectory (p); }

Ha azonban egyetlen hívással szeretnénk létrehozni a könyvtárak hierarchiáját, akkor a createDirectories módszer. Az előző művelettel ellentétben, amikor az útvonalon hiányzó névelemekkel találkozik, nem dob egy IOException, rekurzív módon létrehozza őket az utolsó elemig:

@Test public void givenDirPath_whenCreatesRecursively_thenCorrect () {Útvonal dir = Paths.get (HOME + "/ myDir_" + UUID.randomUUID (). ToString ()); Útvonal alkönyvtár = dir.resolve ("alkönyvtár"); assertFalse (Fájlok.létezik (dir)); assertFalse (Files.exists (alkönyvtár)); Files.createDirectories (alkönyvtár); assertTrue (Fájlok.létezik (dir)); assertTrue (Fájlok.létezik (alkönyvtár)); }

5. Ideiglenes fájlok létrehozása

Sok alkalmazás futás közben ideiglenes fájlok nyomvonalát hozza létre a fájlrendszerben. Ennek eredményeként a legtöbb fájlrendszer rendelkezik külön könyvtárral az ilyen alkalmazások által létrehozott ideiglenes fájlok tárolására.

Az új fájlrendszer API speciális műveleteket biztosít erre a célra. A createTempFile Az API végrehajtja ezt a műveletet. Ehhez elérési út objektum, fájl előtag és fájl utótag szükséges:

@Test public void givenFilePath_whenCreatesTempFile_thenCorrect () {String prefix = "log_"; Karakterlánc utótag = ".txt"; Path p = Paths.get (HOME + "/"); Files.createTempFile (p, előtag, utótag); assertTrue (Fájlok.létezik (p)); }

Ezek a paraméterek elegendőek a műveletet igénylő követelményekhez. Ha azonban meg kell adnia a fájl meghatározott attribútumait, akkor van egy negyedik változó argumentum paraméter.

A fenti teszt egy ideiglenes fájlt hoz létre a ITTHON könyvtár, a függőleges és a mellékelt előtag- és utótag-karakterláncok függőben vannak. Végül egy ilyen fájlnévvel találkozunk log_8821081429012075286.txt. A hosszú numerikus karakterláncot a rendszer generálja.

Ha azonban nem adunk meg előtagot és utótagot, akkor a fájlnév csak a hosszú numerikus karakterláncot és egy alapértelmezettet tartalmaz .tmp kiterjesztés:

@Test public void givenPath_whenCreatesTempFileWithDefaults_thenCorrect () {Path p = Paths.get (HOME + "/"); Files.createTempFile (p, null, null); assertTrue (Fájlok.létezik (p)); }

A fenti művelet egy ilyen nevű fájlt hoz létre 8600179353689423985.tmp.

Végül, ha nem adunk meg sem utat, sem előtagot, sem utótagot, akkor a művelet az alapértelmezéseket használja. A létrehozott fájl alapértelmezett helye a fájlrendszer által biztosított ideiglenes fájl könyvtár lesz:

@Test public void givenNoFilePath_whenCreatesTempFileInTempDir_thenCorrect () {Path p = Files.createTempFile (null, null); assertTrue (Fájlok.létezik (p)); }

Windows rendszeren ez alapértelmezés szerint valami hasonló lesz C: \ Users \ user \ AppData \ Local \ Temp \ 6100927974988978748.tmp.

A fenti műveletek alkalmazhatók könyvtárak létrehozására, nem pedig normál fájlok használatával createTempDirectory ahelyett createTempFile.

6. Fájl törlése

Fájl törléséhez a töröl API. Az egyértelműség kedvéért a következő teszt először biztosítja, hogy a fájl még nem létezik, majd létrehozza, megerősíti, hogy létezik, végül törli, és megerősíti, hogy már nem létezik:

@Test public void givenPath_whenDeletes_thenCorrect () {Path p = Paths.get (HOME + "/fileToDelete.txt"); assertFalse (Fájlok.létezik (p)); Files.createFile (p); assertTrue (Fájlok.létezik (p)); Files.delete (p); assertFalse (Fájlok.létezik (p)); }

Ha azonban egy fájl nem létezik a fájlrendszerben, akkor a törlési művelet sikertelen lesz egy IOException:

@Test (várható = NoSuchFileException.class) public void givenInexistentFile_whenDeleteFails_thenCorrect () {Path p = Paths.get (HOME + "/inexistentFile.txt"); assertFalse (Fájlok.létezik (p)); Files.delete (p); }

Használatával elkerülhetjük ezt a forgatókönyvet deleteIfExists amelyek csendesen kudarcot vallanak abban az esetben, ha a fájl nem létezik. Ez akkor fontos, ha több szál végzi ezt a műveletet, és nem akarunk hibaüzenetet egyszerűen azért, mert egy szál korábban hajtotta végre a műveletet, mint a jelenlegi sikertelen szál:

@Test public void givenInexistentFile_whenDeleteIfExistsWorks_thenCorrect () {Path p = Paths.get (HOME + "/inexistentFile.txt"); assertFalse (Fájlok.létezik (p)); Files.deleteIfExists (p); }

A könyvtárakkal és nem a szokásos fájlokkal való foglalkozás során emlékeznünk kell arra, hogy a törlési művelet alapértelmezés szerint nem működik rekurzív módon. Tehát ha egy könyvtár nem üres, akkor egy IOException:

@Test (várható = DirectoryNotEmptyException.class) public void givenPath_whenFailsToDeleteNonEmptyDir_thenCorrect () {Path dir = Paths.get (HOME + "/ emptyDir" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir); assertTrue (Fájlok.létezik (dir)); Útvonal fájl = dir.resolve ("file.txt"); Files.createFile (fájl); Files.delete (dir); assertTrue (Fájlok.létezik (dir)); }

7. Fájlok másolása

A fájlt vagy könyvtárat a másolat API:

@Test public void givenFilePath_whenCopiesToNewLocation_thenCorrect () {Dirath path = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Útvonal dir2 = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Útvonal fájl1 = dir1.resolve ("filetocopy.txt"); Útvonalfájl2 = dir2.resolve ("filetocopy.txt"); Files.createFile (fájl1); assertTrue (Fájlok.létezik (fájl1)); assertFalse (Fájlok.létezik (fájl2)); Files.copy (fájl1, fájl2); assertTrue (Fájlok.létezik (fájl2)); }

A másolás sikertelen, ha a célfájl létezik, hacsak a REPLACE_EXISTING opció van megadva:

@Test (várható = FileAlreadyExistsException.class) public void givenPath_whenCopyFailsDueToExistingFile_thenCorrect () {Útvonal dir1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Útvonal dir2 = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Útvonal fájl1 = dir1.resolve ("filetocopy.txt"); Útvonalfájl2 = dir2.resolve ("filetocopy.txt"); Files.createFile (fájl1); Files.createFile (fájl2); assertTrue (Fájlok.létezik (fájl1)); assertTrue (Fájlok.létezik (fájl2)); Files.copy (fájl1, fájl2); Files.copy (fájl1, fájl2, StandardCopyOption.REPLACE_EXISTING); }

Könyvtárak másolásakor azonban a tartalom nem kerül rekurzív módon másolásra. Ez azt jelenti, hogy ha / baeldung tartalmazza /articles.db és /authors.db fájlok, másolás / baeldung új helyre egy üres könyvtárat hoz létre.

8. Fájlok mozgatása

A fájlt vagy könyvtárat áthelyezheti a mozog API. A legtöbb szempontból hasonló a másolat művelet. Ha a másolási művelet analóg a másolás és beillesztés akkor a GUI alapú rendszerekben való működés mozog analóg a kivágás és beillesztés művelet:

@Test public void givenFilePath_whenMovesToNewLocation_thenCorrect () {Dirath path1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Útvonal dir2 = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Útvonal fájl1 = dir1.resolve ("filetocopy.txt"); Útvonalfájl2 = dir2.resolve ("filetocopy.txt"); Files.createFile (fájl1); assertTrue (Fájlok.létezik (fájl1)); assertFalse (Fájlok.létezik (fájl2)); Files.move (fájl1, fájl2); assertTrue (Fájlok.létezik (fájl2)); assertFalse (Fájlok.létezik (fájl1)); }

A mozog művelet sikertelen, ha a célfájl létezik, hacsak a REPLACE_EXISTING opció pontosan meg van adva, mint mi a másolat művelet:

@Test (várható = FileAlreadyExistsException.class) public void givenFilePath_whenMoveFailsDueToExistingFile_thenCorrect () {Útvonal dir1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Útvonal dir2 = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Útvonal fájl1 = dir1.resolve ("filetocopy.txt"); Útvonalfájl2 = dir2.resolve ("filetocopy.txt"); Files.createFile (fájl1); Files.createFile (fájl2); assertTrue (Fájlok.létezik (fájl1)); assertTrue (Fájlok.létezik (fájl2)); Files.move (fájl1, fájl2); Files.move (fájl1, fájl2, StandardCopyOption.REPLACE_EXISTING); assertTrue (Fájlok.létezik (fájl2)); assertFalse (Fájlok.létezik (fájl1)); }

9. Következtetés

Ebben a cikkben megismerkedtünk a fájl API-kkal az új fájlrendszer API-ban (NIO2), amelyet a Java 7 részeként szállítottak le, és a fontos fájlműveletek többségét működés közben látták.

Az ebben a cikkben használt kódminták a cikk Github projektjében találhatók.