Daten einlesen (Java): Unterschied zwischen den Versionen

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen
K (Zeichen von der Konsole einlesen)
K
 
(4 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
Um mit Java Daten einzulesen hat man mehrere Möglichkeiten von Bytestreams und Characterstreams.
+
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.
 
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.
  
[[Klasse]] die für das Einlesen von Daten zuständig sind haben immer ein Input, bei Binärstreams oder Reader, bei Charachterstreams im Namen.
+
[[Klasse|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=
 
=Binär Streams=
 
Um Binärdaten einzulesen können alle Streams verwendet werden die vom {{JAPI|InputStream}} abgeleitet sind, so z.B. der {{JAPI|FileInputStream}} oder auch der {{JAPI|BufferedInputStream}}.
 
Um Binärdaten einzulesen können alle Streams verwendet werden die vom {{JAPI|InputStream}} abgeleitet sind, so z.B. der {{JAPI|FileInputStream}} oder auch der {{JAPI|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.
+
Der FileInputStream ist der einzigste Bytestream der direkt auf Dateien zugreifen kann, daher wird er verwendet, wenn man Daten aus eine [[Datei]] einlesen will.
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
 
FileInputStream fin = new FileInputStream("datei");
 
FileInputStream fin = new FileInputStream("datei");
 
</syntaxhighlight>
 
</syntaxhighlight>
Hat man keine Datei sondern bekommt einen Stream, z.B. von einem {{JAPI|Socket}} kann man für diese ein InputStream [[Objekt]] deklarieren.
+
Hat man keine Datei sondern bekommt einen Stream, z.B. von einem {{JAPI|Socket}} kann man für diese ein InputStream-[[Objekt]] deklarieren.
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
 
InputStream in = socket.getInputStream();
 
InputStream in = socket.getInputStream();
 
</syntaxhighlight>
 
</syntaxhighlight>
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.
+
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.
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
 
BufferedInputStream bufin = new BufferedInputStream(in);
 
BufferedInputStream bufin = new BufferedInputStream(in);
 
</syntaxhighlight>
 
</syntaxhighlight>
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, dieser 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.
+
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.
 
Alle drei Methoden haben gemeinsam, dass wenn sie am Ende des Streams angelangt sind, -1 zurückgeben.
 
Einlesen einer ganzen Datei:
 
Einlesen einer ganzen Datei:
Zeile 50: Zeile 50:
  
 
=Character Streams=
 
=Character Streams=
Um Zeichenketten einzulesen nimmt man meistens Klassen die von {{JAPI|Reader}} abgeleitet sind, so z.B. {{JAPI|FileReader}} oder {{JAPI|BufferedReader}}. Diese Klassen bieten meistens auch die Möglichkeit die Daten in einen bestimmten [[Zeichensatz]] zu konvertieren.
+
Um Zeichenketten einzulesen, nimmt man meistens Klassen die von {{JAPI|Reader}} abgeleitet sind, so z.B. {{JAPI|FileReader}} oder {{JAPI|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.
 
Wie bei den Binärstreams gibt es auch hier nur einen Stream der nur direkt auf Dateien geht, der FileReader.
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
Zeile 106: Zeile 106:
  
 
===Einlesen mit {{JAPI|BufferedReader}}===
 
===Einlesen mit {{JAPI|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.
 
Dem gepufferten Reader wird ein Inputstream übergeben, welchem wiederum die Datenquelle übergeben wird, aus der die Daten gelesen werden sollen. Hier also die Tastatur.
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
Zeile 118: Zeile 120:
  
 
===Einlesen mit {{JAPI|Scanner}}===
 
===Einlesen mit {{JAPI|Scanner}}===
Die Codezeile für das Lesen mit einem Scanner sieht ziemlich ähnlich aus:
+
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:
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
 
Scanner reader = new Scanner(System.in));
 
Scanner reader = new Scanner(System.in));
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Zum Einlesen beliebiger Zeichenketten von der Tastatur kann die next()-Methode eingesetzt werden:
+
Zum Einlesen beliebiger Zeichenketten von der Tastatur kann die <code>next()</code>-Methode eingesetzt werden:
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
 
System.out.print("Gib deinen Namen ein: ");
 
System.out.print("Gib deinen Namen ein: ");
 
String line = reader.next(); //auslesen der Tastatureingabe
 
String line = reader.next(); //auslesen der Tastatureingabe
 
</syntaxhighlight>
 
</syntaxhighlight>
Scanner kennt noch viele weitere Methoden zum Einlesen, die an bestimmte Datentypen angepasst sind.
+
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):
 +
<syntaxhighlight lang="java">
 +
System.out.print("Gib eine Dezimalzahl ein: ");
 +
double line = reader.nextDouble(); //auslesen der Tastatureingabe
 +
</syntaxhighlight>
  
 
[[Kategorie:Java]]
 
[[Kategorie:Java]]
 
[[Kategorie:Tutorials (Java)]]
 
[[Kategorie:Tutorials (Java)]]

Aktuelle Version vom 18. November 2021, 15:36 Uhr

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