Úvod do Java NIO2 File API

1. Prehľad

V tomto článku sa zameriame na nové I / O API v platforme Java - NIO2 - robiť základnú manipuláciu so súbormi.

File API v NIO2 tvoria jednu z hlavných nových funkčných oblastí platformy Java, ktorá sa dodáva s jazykom Java 7, konkrétne podmnožina nového API systému súborov spolu s Path API.

2. Inštalácia

Nastavenie vášho projektu na používanie File API je len otázkou uskutočnenia tohto importu:

import java.nio.file. *;

Pretože ukážky kódu v tomto článku budú pravdepodobne spustené v rôznych prostrediach, poďme získať popis k domovskému adresáru používateľa, ktorý bude platný pre všetky operačné systémy:

private static String HOME = System.getProperty ("user.home");

The Súbory trieda je jedným z primárnych vstupných bodov do java.nio.file balíček. Táto trieda ponúka bohatú sadu rozhraní API na čítanie, zápis a manipuláciu so súbormi a adresármi. The Súbory triedne metódy pracujú na inštanciách Cesta predmety.

3. Kontrola súboru alebo adresára

Môžeme mať Cesta inštancia predstavujúca súbor alebo adresár v súborovom systéme. Či súbor alebo adresár, na ktorý ukazuje, existuje alebo nie, je prístupný alebo nie, je možné potvrdiť operáciou so súborom.

Kvôli jednoduchosti, kedykoľvek tento výraz použijeme spis, budeme odkazovať na súbory aj adresáre, pokiaľ nie je výslovne uvedené inak.

Na kontrolu existencie súboru používame existuje API:

@Test public void givenExistentPath_whenConfirmsFileExists_thenCorrect () {Cesta p = Cesta.get (DOMOV); assertTrue (Files.exists (p)); }

Na kontrolu toho, či súbor neexistuje, používame nieExistuje API:

@Test public void givenNonexistentPath_whenConfirmsFileNotExists_thenCorrect () {Cesta p = Cesty.get (HOME + "/inexistent_file.txt"); assertTrue (Files.notExists (p)); }

Môžeme tiež skontrolovať, či ide o bežný súbor myfile.txt alebo je to iba adresár, používame isRegularFile API:

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

Existujú tiež statické metódy na kontrolu povolení súborov. Na kontrolu čitateľnosti súboru používame je čitateľný API:

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

Na kontrolu, či je zapisovateľný, používame isWritable API:

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

Podobne skontrolujte, či je spustiteľný:

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

Keď máme dve cesty, môžeme skontrolovať, či obe smerujú na rovnaký súbor v základnom systéme súborov:

@Test public void givenSameFilePaths_whenConfirmsIsSame_thenCorrect () {Cesta p1 = Cesta.get (HOME); Cesta p2 = Cesty.get (DOMOV); assertTrue (Files.isSameFile (p1, p2)); }

4. Vytváranie súborov

Rozhranie API súborového systému poskytuje na vytváranie súborov operácie jedného riadku. Na vytvorenie bežného súboru používame createFile API a odovzdať mu a Cesta objekt predstavujúci súbor, ktorý chceme vytvoriť.

Všetky prvky názvu v ceste musia existovať, okrem názvu súboru, inak dostaneme znak Výnimka IO:

@Test public void givenFilePath_whenCreatesNewFile_thenCorrect () {String fileName = "myfile_" + UUID.randomUUID (). ToString () + ".txt"; Cesta p = Cesty.get (DOMOV + "/" + nazov souboru); assertFalse (Files.exists (p)); Files.createFile (p); assertTrue (Files.exists (p)); }

Vo vyššie uvedenom teste, keď najskôr skontrolujeme cestu, je neexistujúca a potom po nej createFile sa zistilo, že existuje.

Na vytvorenie adresára používame createDirectory API:

@Test public void givenDirPath_whenCreatesNewDir_thenCorrect () {String dirName = "myDir_" + UUID.randomUUID (). ToString (); Cesta p = Cesty.get (HOME + "/" + dirName); assertFalse (Files.exists (p)); Files.createDirectory (p); assertTrue (Files.exists (p)); assertFalse (Files.isRegularFile (p)); assertTrue (Files.isDirectory (p)); }

Táto operácia vyžaduje, aby existovali všetky prvky názvu v ceste, ak nie, dostaneme tiež znak Výnimka IO:

@Test (expect = NoSuchFileException.class) public void givenDirPath_whenFailsToCreateRecursively_thenCorrect () {String dirName = "myDir_" + UUID.randomUUID (). ToString () + "/ subdir"; Cesta p = Cesty.get (HOME + "/" + dirName); assertFalse (Files.exists (p)); Files.createDirectory (p); }

Ak však chceme vytvoriť hierarchiu adresárov jediným volaním, použijeme znak createDirectories metóda. Na rozdiel od predchádzajúcej operácie, keď narazí na chýbajúce prvky názvu v ceste, nevyvolá znak Výnimka IO, vytvára ich rekurzívne až k poslednému prvku:

@Test public void givenDirPath_whenCreatesRecursively_thenCorrect () {Path dir = Paths.get (HOME + "/ myDir_" + UUID.randomUUID (). ToString ()); Cesta subdir = dir.resolve ("subdir"); assertFalse (Files.exists (dir)); assertFalse (Files.exists (subdir)); Files.createDirectories (podadresár); assertTrue (Files.exists (dir)); assertTrue (Files.exists (subdir)); }

5. Vytváranie dočasných súborov

Mnoho aplikácií vytvára počas spustenia stopu dočasných súborov v súborovom systéme. Výsledkom je, že väčšina súborových systémov má vyhradený adresár na ukladanie dočasných súborov generovaných týmito aplikáciami.

Nové rozhranie API súborového systému poskytuje na tento účel špecifické operácie. The createTempFile Túto operáciu vykonáva API. Trvá objekt cesty, predpona súboru a prípona súboru:

@Test public void givenFilePath_whenCreatesTempFile_thenCorrect () {prefix reťazca = "log_"; Prípona reťazca = ".txt"; Cesta p = Cesty.get (HOME + "/"); Files.createTempFile (p, predpona, prípona); assertTrue (Files.exists (p)); }

Tieto parametre sú dostatočné na splnenie požiadaviek, ktoré si vyžadujú túto operáciu. Ak však potrebujete určiť konkrétne atribúty súboru, existuje štvrtý parameter premenných argumentov.

Vyššie uvedený test vytvorí dočasný súbor v priečinku DOMOV adresár, predbežné čakanie a pripojenie poskytnutých reťazcov predpôn a prípon. Skončíme s názvom súboru ako log_8821081429012075286.txt. Dlhý číselný reťazec je generovaný systémom.

Ak však neposkytneme predponu a príponu, potom bude názov súboru obsahovať iba dlhý číselný reťazec a predvolený .tmp rozšírenie:

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

Vyššie uvedená operácia vytvorí súbor s názvom ako 8600179353689423985.tmp.

Nakoniec, ak neposkytneme ani cestu, predponu ani príponu, potom bude operácia v celom texte používať predvolené hodnoty. Predvolené umiestnenie vytvoreného súboru bude adresár dočasného súboru poskytnutý systémom súborov:

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

V oknách bude mať predvolené nastavenie niečo ako C: \ Users \ user \ AppData \ Local \ Temp \ 6100927974988978748.tmp.

Všetky vyššie uvedené operácie je možné pomocou použitia upraviť na vytváranie adresárov a nie bežných súborov createTempDirectory namiesto createTempFile.

6. Vymazanie súboru

Na odstránenie súboru používame vymazať API. Nasledujúci test z dôvodu prehľadnosti najskôr zabezpečí, aby súbor ešte neexistoval, potom ho vytvorí a potvrdí, že už existuje, a nakoniec ho odstráni a potvrdí, že už neexistuje:

@Test public void 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)); }

Ak však súbor v systéme súborov neexistuje, operácia odstránenia zlyhá pri znaku Výnimka IO:

@Test (očakáva sa = NoSuchFileException.class) public void givenInexistentFile_whenDeleteFails_thenCorrect () {Cesta p = Cesty.get (HOME + "/inexistentFile.txt"); assertFalse (Files.exists (p)); Files.delete (p); }

Tomuto scenáru sa môžeme vyhnúť použitím deleteIfExists ktoré ticho zlyhajú v prípade, že súbor neexistuje. To je dôležité, keď túto operáciu vykonáva viac vlákien a my nechceme správu o zlyhaní len preto, že vlákno vykonalo operáciu skôr ako súčasné vlákno, ktoré zlyhalo:

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

Keď pracujeme s adresármi a nie s bežnými súbormi, mali by sme pamätať na to, že operácia mazania štandardne nefunguje rekurzívne. Takže ak adresár nie je prázdny, zlyhá s Výnimka IO:

@Test (očakáva sa = DirectoryNotEmptyException.class) public void givenPath_whenFailsToDeleteNonEmptyDir_thenCorrect () {Path dir = Paths.get (HOME + "/ emptyDir" + UUID.randomUUID (). ToString ()); Files.createDirectory (adresár); assertTrue (Files.exists (dir)); Cesta file = dir.resolve ("file.txt"); Files.createFile (súbor); Files.delete (dir); assertTrue (Files.exists (dir)); }

7. Kopírovanie súborov

Môžete skopírovať súbor alebo adresár pomocou kópia API:

@Test public void givenFilePath_whenCopiesToNewLocation_thenCorrect () {Path dir1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Path dir2 = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Cesta file1 = dir1.resolve ("filetocopy.txt"); Cesta file2 = dir2.resolve ("filetocopy.txt"); Files.createFile (súbor1); assertTrue (Files.exists (file1)); assertFalse (Files.exists (file2)); Files.copy (súbor1, súbor2); assertTrue (Files.exists (file2)); }

Kópia zlyhá, ak cieľový súbor existuje, pokiaľ REPLACE_EXISTING je zadaná možnosť:

@Test (expect = FileAlreadyExistsException.class) public void givenPath_whenCopyFailsDueToExistingFile_thenCorrect () {Path dir1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Cesta dir2 = Cesta.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Cesta file1 = dir1.resolve ("filetocopy.txt"); Cesta file2 = dir2.resolve ("filetocopy.txt"); Files.createFile (súbor1); Files.createFile (file2); assertTrue (Files.exists (file1)); assertTrue (Files.exists (file2)); Files.copy (súbor1, súbor2); Files.copy (súbor1, súbor2, StandardCopyOption.REPLACE_EXISTING); }

Pri kopírovaní adresárov sa však obsah nekopíruje rekurzívne. To znamená, že ak / baeldung obsahuje /articles.db a /authors.db súbory, kopírovanie / baeldung na nové miesto vytvorí prázdny adresár.

8. Presun súborov

Súbor alebo adresár môžete presunúť pomocou pohnúť sa API. Je to vo väčšine ohľadov podobné kópia prevádzka. Ak je operácia kopírovania analogická k a kopírovanie a vkladanie potom v systémoch založených na GUI pohnúť sa je analogický k a vystrihnúť a prilepiť prevádzka:

@Test public void givenFilePath_whenMovesToNewLocation_thenCorrect () {Path dir1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Path dir2 = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Cesta file1 = dir1.resolve ("filetocopy.txt"); Cesta file2 = dir2.resolve ("filetocopy.txt"); Files.createFile (súbor1); assertTrue (Files.exists (file1)); assertFalse (Files.exists (file2)); Files.move (súbor1, súbor2); assertTrue (Files.exists (file2)); assertFalse (Files.exists (file1)); }

The pohnúť sa operácia zlyhá, ak cieľový súbor existuje, pokiaľ REPLACE_EXISTING možnosť je zadaná rovnako ako pri kópia prevádzka:

@Test (expect = FileAlreadyExistsException.class) public void givenFilePath_whenMoveFailsDueToExistingFile_thenCorrect () {Path dir1 = Paths.get (HOME + "/ firstdir_" + UUID.randomUUID (). ToString ()); Path dir2 = Paths.get (HOME + "/ otherdir_" + UUID.randomUUID (). ToString ()); Files.createDirectory (dir1); Files.createDirectory (dir2); Cesta file1 = dir1.resolve ("filetocopy.txt"); Cesta file2 = dir2.resolve ("filetocopy.txt"); Files.createFile (súbor1); Files.createFile (súbor2); assertTrue (Files.exists (file1)); assertTrue (Files.exists (file2)); Files.move (súbor1, súbor2); Files.move (súbor1, súbor2, StandardCopyOption.REPLACE_EXISTING); assertTrue (Files.exists (file2)); assertFalse (Files.exists (file1)); }

9. Záver

V tomto článku sme sa dozvedeli o súborových API v novom súborovom systéme API (NIO2), ktorý bol dodaný ako súčasť Java 7, a videli sme väčšinu dôležitých operácií so súbormi v akcii.

Ukážky kódu použité v tomto článku nájdete v projekte Github tohto článku.