Una guida alla classe FileReader Java

1. Panoramica

Come suggerisce il nome, FileReader è una classe Java che semplifica la lettura del contenuto di un file .

In questo tutorial, impareremo il concetto di base di un Reader e come possiamo utilizzare la classe FileReader per eseguire operazioni di lettura su un flusso di caratteri in Java.

2. Nozioni di base sul lettore

Se guardiamo il codice della classe FileReader , noteremo che la classe contiene un codice minimo per creare un oggetto FileReader e nessun altro metodo.

Ciò solleva domande come "Chi fa il lavoro pesante dietro questa classe?"

Per rispondere a questa domanda, dobbiamo comprendere il concetto e la gerarchia della classe Reader in Java.

Reader è una classe base astratta che rende possibile la lettura dei caratteri attraverso una delle sue implementazioni concrete. Definisce le seguenti operazioni di base di lettura dei caratteri da qualsiasi supporto come la memoria o il filesystem:

  • Leggi un singolo carattere
  • Leggi una serie di caratteri
  • Contrassegna e ripristina una determinata posizione in un flusso di caratteri
  • Salta la posizione durante la lettura di un flusso di caratteri
  • Chiudi il flusso di input

Naturalmente, tutte le implementazioni della classe Reader devono implementare tutti i metodi astratti, ovvero read () e close () . Inoltre, la maggior parte delle implementazioni sovrascrive anche altri metodi ereditati per fornire funzionalità aggiuntive o prestazioni migliori.

2.1. Quando utilizzare un FileReader

Ora che abbiamo una certa comprensione di un lettore , siamo pronti per riportare la nostra attenzione sulla classe FileReader .

FileReader eredita la sua funzionalità da InputStreamReader , che è un'implementazione di Reader progettata per leggere byte da un flusso di input come caratteri.

Vediamo questa gerarchia nelle definizioni delle classi:

public class InputStreamReader extends Reader {} public class FileReader extends InputStreamReader {}

In generale, possiamo usare un InputStreamReader per leggere i caratteri da qualsiasi sorgente di input.

Tuttavia, quando si tratta di leggere il testo da un file, usare un InputStreamReader sarebbe come tagliare una mela con una spada. Naturalmente, lo strumento giusto sarebbe un coltello, che è esattamente ciò che FileReader promette.

Possiamo usare un FileReader quando vogliamo leggere il testo da un file usando il set di caratteri predefinito del sistema. Per qualsiasi altra funzionalità avanzata, sarebbe l'ideale per utilizzare direttamente la classe InputStreamReader .

3. Leggere un file di testo con un FileReader

Esaminiamo un esercizio di codifica per leggere i caratteri da un file HelloWorld.txt utilizzando un'istanza di FileReader .

3.1. Creazione di un FileReader

Come classe di convenienza, FileReader offre tre costruttori sovraccaricati che possono essere utilizzati per inizializzare un lettore in grado di leggere da un file come origine di input.

Diamo un'occhiata a questi costruttori:

public FileReader(String fileName) throws FileNotFoundException { super(new FileInputStream(fileName)); } public FileReader(File file) throws FileNotFoundException { super(new FileInputStream(file)); } public FileReader(FileDescriptor fd) { super(new FileInputStream(fd)); }

Nel nostro caso, conosciamo il nome del file di input. Di conseguenza, possiamo usare il primo costruttore per inizializzare un lettore:

FileReader fileReader = new FileReader(path);

3.2. Leggere un singolo personaggio

Successivamente, creiamo readAllCharactersOneByOne () , un metodo per leggere i caratteri dal file uno alla volta:

public static String readAllCharactersOneByOne(Reader reader) throws IOException { StringBuilder content = new StringBuilder(); int nextChar; while ((nextChar = reader.read()) != -1) { content.append((char) nextChar); } return String.valueOf(content); }

Come possiamo vedere dal codice sopra, abbiamo utilizzato il metodo read () in un ciclo per leggere i caratteri uno per uno fino a quando non restituisce -1 , il che significa che non ci sono più caratteri da leggere.

Ora, testiamo il nostro codice convalidando che il testo letto dal file corrisponda al testo previsto:

@Test public void givenFileReader_whenReadAllCharacters_thenReturnsContent() throws IOException { String expectedText = "Hello, World!"; File file = new File(FILE_PATH); try (FileReader fileReader = new FileReader(file)) { String content = FileReaderExample.readAllCharactersOneByOne(fileReader); Assert.assertEquals(expectedText, content); } }

3.3. Lettura di una matrice di caratteri

Possiamo persino leggere più caratteri contemporaneamente utilizzando il metodo di lettura ereditato (char cbuf [], int off, int len) :

public static String readMultipleCharacters(Reader reader, int length) throws IOException { char[] buffer = new char[length]; int charactersRead = reader.read(buffer, 0, length); if (charactersRead != -1) { return new String(buffer, 0, charactersRead); } else { return ""; } }

C'è una sottile differenza nel valore restituito da read () quando si tratta di leggere più caratteri in un array. Il valore restituito qui è il numero di caratteri letti o -1 se il lettore ha raggiunto la fine del flusso di input.

Successivamente, testiamo la correttezza del nostro codice:

@Test public void givenFileReader_whenReadMultipleCharacters_thenReturnsContent() throws IOException { String expectedText = "Hello"; File file = new File(FILE_PATH); try (FileReader fileReader = new FileReader(file)) { String content = FileReaderExample.readMultipleCharacters(fileReader, 5); Assert.assertEquals(expectedText, content); } }

4. Limitazioni

Abbiamo visto che la classe FileReader si basa sulla codifica dei caratteri di sistema predefinita.

Pertanto, per le situazioni in cui è necessario utilizzare valori personalizzati per il set di caratteri, la dimensione del buffer o il flusso di input, è necessario utilizzare InputStreamReader .

Inoltre, sappiamo tutti che i cicli di I / O sono costosi e possono introdurre latenza nella nostra applicazione. Quindi, è nel nostro migliore interesse ridurre al minimo il numero di operazioni di I / O avvolgendo un BufferedReader attorno al nostro oggetto FileReader :

BufferedReader in = new BufferedReader(fileReader);

5. conclusione

In questo tutorial, abbiamo imparato i concetti di base di un Reader e come FileReader semplifica le operazioni di lettura sui file di testo attraverso alcuni esempi.

Come sempre, il codice sorgente completo del tutorial è disponibile su GitHub.