Opzioni di apertura dei file Java

1. Panoramica

In questo tutorial, ci concentreremo sulle opzioni di apertura standard disponibili per i file in Java.

Esploreremo l' enumerazione StandardOpenOption che implementa l' interfaccia OpenOption e che definisce queste opzioni aperte standard.

2. Il parametro OpenOption

In Java, possiamo lavorare con i file utilizzando l'API NIO2, che contiene diversi metodi di utilità. Alcuni di questi metodi utilizzano un parametro OpenOption facoltativo che configura come aprire o creare un file. Inoltre, questo parametro avrà un valore predefinito se non impostato, che può essere diverso per ciascuno di questi metodi.

Il tipo di enumerazione StandardOpenOption definisce le opzioni standard e implementa l' interfaccia OpenOption .

Ecco l'elenco delle opzioni supportate che possiamo utilizzare con l' enumerazione StandardOpenOptions :

  • SCRIVI : apre il file per l'accesso in scrittura
  • APPEND : aggiunge alcuni dati al file
  • TRUNCATE_EXISTING : tronca il file
  • CREATE_NEW : crea un nuovo file e genera un'eccezione se il file esiste già
  • CREA : apre il file se esiste o crea un nuovo file se non lo è
  • DELETE_ON_CLOSE : elimina il file dopo aver chiuso lo stream
  • SPARSE : il file appena creato sarà scarso
  • SYNC : conserva il contenuto e i metadati del file sincronizzato
  • DSYNC : conserva solo il contenuto del file sincronizzato

Nelle prossime sezioni vedremo esempi di come utilizzare ciascuna di queste opzioni.

Per evitare qualsiasi confusione sul percorso del file, prendiamo un handle sulla directory home dell'utente, che sarà valido su tutti i sistemi operativi:

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

3. Apertura di un file per la lettura e la scrittura

Innanzitutto, se vogliamo creare un nuovo file se non esiste possiamo usare l'opzione CREA :

@Test public void givenExistingPath_whenCreateNewFile_thenCorrect() throws IOException { assertFalse(Files.exists(Paths.get(HOME, "newfile.txt"))); Files.write(path, DUMMY_TEXT.getBytes(), StandardOpenOption.CREATE); assertTrue(Files.exists(path)); }

Possiamo anche usare l'opzione CREATE_NEW, che creerà un nuovo file se non esiste. Tuttavia, genererà un'eccezione se il file esiste già.

In secondo luogo, se vogliamo aprire il file in lettura possiamo utilizzare il metodo newInputStream (Path, OpenOption ...). Questo metodo apre il file per la lettura e restituisce un flusso di input:

@Test public void givenExistingPath_whenReadExistingFile_thenCorrect() throws IOException { Path path = Paths.get(HOME, DUMMY_FILE_NAME); try (InputStream in = Files.newInputStream(path); BufferedReader reader = new BufferedReader(new InputStreamReader(in))) { String line; while ((line = reader.readLine()) != null) { assertThat(line, CoreMatchers.containsString(DUMMY_TEXT)); } } } 

Si noti come non abbiamo utilizzato l'opzione READ perché è utilizzata di default dal metodo newInputStream .

Terzo, possiamo creare un file, aggiungerlo a un file o scrivere su un file utilizzando il metodo newOutputStream (Path, OpenOption ...). Questo metodo apre o crea un file per la scrittura e restituisce un OutputStream .

L'API creerà un nuovo file se non specifichiamo le opzioni di apertura e il file non esiste. Tuttavia, se il file esiste, verrà troncato. Questa opzione è simile alla chiamata del metodo con le opzioni CREATE e TRUNCATE_EXISTING .

Apriamo un file esistente e aggiungiamo alcuni dati:

@Test public void givenExistingPath_whenWriteToExistingFile_thenCorrect() throws IOException { Path path = Paths.get(HOME, DUMMY_FILE_NAME); try (OutputStream out = Files.newOutputStream(path, StandardOpenOption.APPEND, StandardOpenOption.WRITE)) { out.write(ANOTHER_DUMMY_TEXT.getBytes()); } }

4. Creazione di un file SPARSE

Possiamo dire al file system che il file appena creato dovrebbe essere scarso (file contenenti spazi vuoti che non verranno scritti su disco).

Per questo, dovremmo usare l'opzione SPARSE con l' opzione CREATE_NEW . Tuttavia, questa opzione verrà ignorata se il file system non supporta i file sparsi .

Creiamo un file sparse:

@Test public void givenExistingPath_whenCreateSparseFile_thenCorrect() throws IOException { Path path = Paths.get(HOME, "sparse.txt"); Files.write(path, DUMMY_TEXT.getBytes(), StandardOpenOption.CREATE_NEW, StandardOpenOption.SPARSE); }

5. Mantenere il file sincronizzato

L' enumerazione StandardOpenOptions ha le opzioni SYNC e DSYNC . Queste opzioni richiedono che i dati vengano scritti nel file in modo sincrono nella memoria. In altre parole, questi garantiranno che i dati non vadano persi in caso di crash del sistema .

Aggiungiamo alcuni dati al nostro file e usiamo l'opzione SYNC :

@Test public void givenExistingPath_whenWriteAndSync_thenCorrect() throws IOException { Path path = Paths.get(HOME, DUMMY_FILE_NAME); Files.write(path, ANOTHER_DUMMY_TEXT.getBytes(), StandardOpenOption.APPEND, StandardOpenOption.WRITE, StandardOpenOption.SYNC); }

La differenza tra SYNC e DSYNC è che SYNC memorizza il contenuto ei metadati del file in modo sincrono nella memoria, mentre DSYNC memorizza solo il contenuto del file in modo sincrono nella memoria.

6. Eliminazione del file dopo la chiusura del flusso

L' enumerazione StandardOpenOptions offre anche un'utile opzione che ci dà la possibilità di distruggere il file dopo aver chiuso lo stream. Questo è utile se vogliamo creare un file temporaneo.

Aggiungiamo alcuni dati al nostro file e utilizziamo l'opzione DELETE_ON_CLOSE :

@Test public void givenExistingPath_whenDeleteOnClose_thenCorrect() throws IOException { Path path = Paths.get(HOME, EXISTING_FILE_NAME); assertTrue(Files.exists(path)); // file was already created and exists try (OutputStream out = Files.newOutputStream(path, StandardOpenOption.APPEND, StandardOpenOption.WRITE, StandardOpenOption.DELETE_ON_CLOSE)) { out.write(ANOTHER_DUMMY_TEXT.getBytes()); } assertFalse(Files.exists(path)); // file is deleted }

7. Conclusione

In questo tutorial, abbiamo trattato le opzioni disponibili per aprire i file in Java utilizzando la nuova API del file system (NIO2) fornita come parte di Java 7.

Come al solito, il codice sorgente con tutti gli esempi nel tutorial può essere trovato su Github.