Daten einlesen (Java)

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen

Um mit Java Daten einzulesen, hat man mehrere Möglichkeiten von Bytestreams und Characterstreams. Bytestreams eignen sich für alle Arten von Daten da alles als Binärdaten vorliegt, Characterstreams eignen sich besonders zum Einlesen und Schreiben von Zeichenketten im ASCII oder anderen Formaten.

Klassen, die für das Einlesen von Daten zuständig sind, haben jeweils ein Input, bei Binärstreams oder Reader, bei Charachterstreams im Namen.

Binär Streams

Um Binärdaten einzulesen können alle Streams verwendet werden die vom InputStream abgeleitet sind, so z.B. der FileInputStream oder auch der BufferedInputStream. Der FileInputStream ist der einzigste Bytestream der direkt auf Dateien zugreifen kann, daher wird er verwendet, wenn man Daten aus eine Datei einlesen will.

FileInputStream fin = new FileInputStream("datei");

Hat man keine Datei sondern bekommt einen Stream, z.B. von einem Socket kann man für diese ein InputStream-Objekt deklarieren.

InputStream in = socket.getInputStream();

Wenn man den Stream hat, kann man dann die Daten aus dem Stream mit den verschiedenen read()-Methoden laden, jedoch kapselt man die einfachen Streams oftmals noch in einem gepufferten Stream, BufferedInputStream um so die Lesezugriffe auf das Medium zu minimieren.

BufferedInputStream bufin = new BufferedInputStream(in);

Nach dem Öffnen des Streams fängt man immer am 1. Byte des Streams an, man kann sich das wie ein Zeiger vorstellen der nach jedem Lesevorgang um die gelesenen Bytes vorbewegt. Die einfache read()-Methode ohne Parameter liest immer nur ein Byte und gibt dieses zurück. Desweiteren gibt es eine read()-Methode die ein byte-Array als Argument bekommt, dieses Array muss vorher angelegt werden und wird dann komplett mit Daten gefüllt und die Anzahl der gelesenen Bytes wird als int-Wert zurückgegeben. So erfährt man, ob der Array komplett voll ist, oder ob er nur teilweise gefüllt wurde. Als dritte Methode gibt es die Methode mit drei Parametern einem byte-Array und zwei int-Werten, der byte-Array wird wie bei der anderen Methode mit Werten gefüllt und die beiden int-Werte beschreiben den Offset (Anzahl der Bytes die nicht gelesen werden) und die maximale Anzahl an Bytes die gelesen werden. Wie auch bei der anderen Methode wird die tatsächliche Anzahl an gelesenen Elementen zurückgegeben. Alle drei Methoden haben gemeinsam, dass wenn sie am Ende des Streams angelangt sind, -1 zurückgeben. Einlesen einer ganzen Datei: 1. nur ein Byte einlesen

int length;
while((length=bufin.read())!=-1)
{
  System.out.println(length);
}

2. immer 250 Byte einlesen

int length;
byte[] buffer = new byte[250];
while((length=bufin.read(buffer))!=-1)
{
  for(int i=0;i!=length;i++)
    System.out.print(buffer[i]);
  System.out.println();
}

3. nur ab dem 250.Byte 4 Byte einlesen

int length;
byte[] buffer = new byte[250];
length=bufin.read(buffer,250,4);
for(int i=0;i!=length;i++)
  System.out.print(buffer[i]);

Character Streams

Um Zeichenketten einzulesen, nimmt man meistens Klassen die von Reader abgeleitet sind, so z.B. FileReader oder BufferedReader. Diese Klassen bieten meistens auch die Möglichkeit die Daten in einen bestimmten Zeichensatz zu konvertieren. Wie bei den Binärstreams gibt es auch hier nur einen Stream der nur direkt auf Dateien geht, der FileReader.

FileReader fin = new FileReader("Datei");

Hat man jedoch nur einen normalen Bytestream und will aber einen Reader verwenden, muss man den vorher Kapselung, dies kann man mit dem InputStreamReader machen.

InputStreamReader in = new InputStreamReader(socket.getInputStream());

Wenn man den Reader hat kann man dann die Zeichen aus dem Stream mit den verschiedenen read()-Methoden laden, jedoch kapselt man die einfachen Streams oftmals noch in einem gepufferten Stream (BufferedReader) um so die Lesezugriffe auf das Medium zu minimieren und auch kompfortabler zu lesen. Denn der BufferedReader besitzt eine readLine()-Methode, welche eine komplette Zeile einliest, die man dann verarbeiten kann.

BufferedReader read = new BufferedReader(in);

Nach dem Öffnen des Readers fängt man immer am 1. Zeichen des Streams an, man kann sich das wie einen Zeiger vorstellen, der nach jedem Lesevorgang um die gelesenen Zeichen vorbewegt. Die einfache read()-Methode ohne Parameter liest immer nur ein Zeichen und gibt dieses zurück. Desweiteren gibt es eine read()-Methode, die ein char-Array als Argument bekommt. Dieser Array muss vorher angelegt werden und wird dann komplett mit Zeichen gefüllt, und die Anzahl der gelesenen Zeichen wird als int-Wert zurückgegeben. So erfährt man, ob der Array komplett voll ist oder ob er nur teilweise gefüllt wurde. Als dritte Methode gibt es die Methode mit drei Parametern einem char-Array und zwei int-Werten. Der char-Array wird wie bei der anderen Methode mit Werten gefüllt und die beiden int-Werte beschreiben den Offset (Anzahl der Zeichen die nicht gelesen werden) und die maximale Anzahl an Zeichen die gelesen werden. Wie auch bei der anderen Methode wird die tatsächliche Anzahl an gelesenen Elementen zurückgegeben. Alle drei Methoden haben gemeinsam, dass wenn sie am Ende des Streams angelangt sind, -1 zurückgeben. Die letzte Methode ist die readLine()-Methode des BufferedReader, diese liest immer eine ganze Zeile ein bis zum \n oder \r oder \r\n und gibt den String ohne den Zeilenumbruch zurück. Ist sie am Ende der Datei angelangt, gibt sie null zurück. Einlesen einer ganzen Datei: 1. nur ein Zeichen einlesen

int length;
while((length=read.read())!=-1)
{
  System.out.println((char)length);
}

2. immer 250 Zeichen einlesen

int length;
char[] buffer = new char[250];
while((length=read.read(buffer))!=-1)
{
  for(int i=0;i!=length;i++)
    System.out.print(buffer[i]);
  System.out.println();
}

3. nur ab dem 250.Zeichen 4 Zeichen einlesen

int length;
char[] buffer = new char[250];
length=read.read(buffer,250,4);
for(int i=0;i!=length;i++)
  System.out.print(buffer[i]);

4. immer eine Zeile einlesen

String line;
while((line=read.readLine())!=null)
  System.out.println(line);

Zeichen von der Konsole einlesen

Im vorigen Kapitel haben wir das Einlesen von Zeichenketten (Strings) aus Streams gesehen, die auf Dateien zeigen. Nun wollen wir uns noch ansehen, wie man Tastatureingaben von der Konsole einliest/entgegennimmt.

Es gibt zwei praktikable Varianten, die sich hinsichtlich ihrer Möglichkeiten unterschieden.

Einlesen mit BufferedReader

Die Klasse BufferedReader ist seit Java 1.1 mit im JDK. Sie verarbeitet Daten aus einem Zeicheneingabe-Datenstrom.

Dem gepufferten Reader wird ein Inputstream übergeben, welchem wiederum die Datenquelle übergeben wird, aus der die Daten gelesen werden sollen. Hier also die Tastatur.

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

Der Reader stellt nun Methoden bereit, um aus dem InputStream zu lesen. Wir geben beim Lesen von der Eingabezeile der readLine()-Methode den Vorzug.

System.out.print("Gib deinen Namen ein: ");
String line = reader.readLine(); //auslesen der Tastatureingabe

Einlesen mit Scanner

Seit Java 5 ist nun auch die recht komfortable Klasse Scanner mit im JDK.

Die Codezeile für das Lesen mit einem Scanner-Objekt sieht ziemlich ähnlich aus:

Scanner reader = new Scanner(System.in));

Zum Einlesen beliebiger Zeichenketten von der Tastatur kann die next()-Methode eingesetzt werden:

System.out.print("Gib deinen Namen ein: ");
String line = reader.next(); //auslesen der Tastatureingabe

Scanner kennt noch viele weitere spezialisierte Methoden zum Einlesen, die an bestimmte primitive Datentypen angepasst sind.

Ein Beispiel für eine Fließkommazahl mit doppelter Genauigkeit (double):

System.out.print("Gib eine Dezimalzahl ein: ");
double line = reader.nextDouble(); //auslesen der Tastatureingabe