Eine Anleitung zur Java FileReader-Klasse

1. Übersicht

Wie der Name schon sagt, ist FileReader eine Java-Klasse, mit der sich der Inhalt einer Datei leicht lesen lässt .

In diesem Tutorial lernen wir das Grundkonzept eines Readers kennen und wie wir die FileReader- Klasse zum Ausführen von Leseoperationen für einen Zeichenstrom in Java verwenden können.

2. Grundlagen des Lesers

Wenn wir uns den Code der FileReader- Klasse ansehen , werden wir feststellen, dass die Klasse nur minimalen Code zum Erstellen eines FileReader- Objekts und keine anderen Methoden enthält.

Dies wirft Fragen auf wie "Wer macht das schwere Heben hinter dieser Klasse?"

Um diese Frage zu beantworten, müssen wir das Konzept und die Hierarchie der Reader- Klasse in Java verstehen .

Reader ist eine abstrakte Basisklasse, die das Lesen von Zeichen durch eine ihrer konkreten Implementierungen ermöglicht. Es definiert die folgenden grundlegenden Operationen zum Lesen von Zeichen von einem beliebigen Medium wie dem Speicher oder dem Dateisystem:

  • Lesen Sie ein einzelnes Zeichen
  • Lesen Sie eine Reihe von Zeichen
  • Markieren Sie eine bestimmte Position in einem Zeichenstrom und setzen Sie sie zurück
  • Überspringen Sie die Position, während Sie einen Zeichenstrom lesen
  • Schließen Sie den Eingabestream

Natürlich müssen alle Implementierungen der Reader- Klasse alle abstrakten Methoden implementieren, nämlich read () und close () . Darüber hinaus überschreiben die meisten Implementierungen auch andere geerbte Methoden, um zusätzliche Funktionen oder eine bessere Leistung zu erzielen.

2.1. Wann wird ein FileReader verwendet ?

Nachdem wir uns mit einem Reader vertraut gemacht haben , können wir uns wieder auf die FileReader- Klasse konzentrieren.

FileReader erbt seine Funktionalität von InputStreamReader , einer Reader- Implementierung zum Lesen von Bytes aus einem Eingabestream als Zeichen.

Sehen wir uns diese Hierarchie in den Klassendefinitionen an:

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

Im Allgemeinen können wir einen InputStreamReader zum Lesen von Zeichen aus einer beliebigen Eingabequelle verwenden.

Wenn Sie jedoch Text aus einer Datei lesen möchten , ist die Verwendung eines InputStreamReader wie das Schneiden eines Apfels mit einem Schwert. Das richtige Werkzeug wäre natürlich ein Messer, genau das verspricht FileReader .

Wir können einen FileReader verwenden, wenn wir Text aus einer Datei mit dem Standardzeichensatz des Systems lesen möchten. Für alle anderen erweiterten Funktionen ist es ideal, die InputStreamReader- Klasse direkt zu verwenden.

3. Lesen einer Textdatei mit einem FileReader

Lassen Sie uns eine Codierungsübung zum Lesen von Zeichen aus einer HelloWorld.txt- Datei mithilfe einer FileReader- Instanz durchführen.

3.1. Erstellen eines FileReader

Als Convenience-Klasse bietet FileReader drei überladene Konstruktoren , mit denen ein Reader initialisiert werden kann, der als Eingabequelle aus einer Datei lesen kann.

Schauen wir uns diese Konstruktoren an:

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)); }

In unserem Fall kennen wir den Dateinamen der Eingabedatei. Folglich können wir den ersten Konstruktor verwenden, um einen Leser zu initialisieren:

FileReader fileReader = new FileReader(path);

3.2. Ein einzelnes Zeichen lesen

Als Nächstes erstellen wir readAllCharactersOneByOne () , eine Methode zum Lesen von Zeichen aus der Datei:

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); }

Wie wir aus dem obigen Code ersehen können , haben wir die read () -Methode in einer Schleife verwendet, um Zeichen einzeln zu lesen, bis -1 zurückgegeben wird , was bedeutet, dass keine Zeichen mehr zu lesen sind.

Testen wir nun unseren Code, indem wir überprüfen, ob der aus der Datei gelesene Text mit dem erwarteten Text übereinstimmt:

@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. Lesen einer Reihe von Zeichen

Mit der geerbten Lesemethode (char cbuf [], int off, int len) können wir sogar mehrere Zeichen gleichzeitig lesen :

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 ""; } }

Es gibt einen subtilen Unterschied im Rückgabewert von read (), wenn es darum geht, mehrere Zeichen in einem Array zu lesen. Der Rückgabewert ist hier entweder die Anzahl der gelesenen Zeichen oder -1, wenn der Leser das Ende des Eingabestreams erreicht hat.

Als nächstes testen wir die Richtigkeit unseres Codes:

@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. Einschränkungen

Wir haben gesehen, dass die FileReader- Klasse auf der Standard-Systemzeichencodierung basiert .

Also, für Situationen, in denen wir müssen benutzerdefinierte Werte verwenden für den Zeichensatz, Puffergröße oder Eingangsstrom, müssen wir verwenden Input .

Darüber hinaus wissen wir alle, dass E / A-Zyklen teuer sind und zu einer Latenz unserer Anwendung führen können. Es liegt daher in unserem besten Interesse, die Anzahl der E / A-Vorgänge zu minimieren, indem ein BufferedReader um unser FileReader- Objekt gewickelt wird :

BufferedReader in = new BufferedReader(fileReader);

5. Schlussfolgerung

In diesem Tutorial haben wir anhand einiger Beispiele die grundlegenden Konzepte eines Readers kennengelernt und erfahren, wie FileReader das Ausführen von Lesevorgängen für Textdateien vereinfacht .

Wie immer ist der vollständige Quellcode für das Tutorial auf GitHub verfügbar.