Ein- und Ausgabe ist im Paket java.io implementiert. Die gliedert sich in die Hauptbereiche
Die Klassen aus java.io benutzt man meist nicht einzeln sondern
in Kombination.
Byte-Ströme dienen zur Speicherung binärer Daten
Byte-Strom-Eingabe wird von der abstrakten Klasse InputStream realisiert:
Beispiel: Zähle die Zeichen in einer Datei
import java.io.*;
class CountChars
{ public static void main(String argv[])
throws IOException
{ InputStream in;
if (argv.length != 0)
in = new FileInputStream(argv[0]);
else in = System.in;
int ch;
int total=0;
while ((ch = in.read()) != -1)
total++;
System.out.println("Number of chars: "
+ total);
}
}
Neben dem oben verwendeten FileInputStream existieren:
Daten aus einem Byte-Array im Speicher lesen.
Teil des Object Serialization
APIs (neu in Java1.1) zur Ausgabe von Objekten
(siehe Seite
).
implementiert die Eingabe-Seite einer Pipe.
konkateniert mehrere Eingabeströme zu
einem (siehe Seite
).
Lesen aus StringBuffer-Objekten (veraltet, daher: deprecated-Meldung).
).
import java.io.*;
class Concatenate
{ public static void main(String[] a)
{ ListOfFiles mylist = new ListOfFiles(a);
try
{ SequenceInputStream s =
new SequenceInputStream(mylist);
int c;
while ((c = s.read()) != -1)
System.out.write(c);
s.close();
}
catch (IOException e)
{ System.err.println
("Concatenate: " + e);
}
}
}
Hier ist die notwendige Enumeration:
import java.util.*;
import java.io.*;
class ListOfFiles implements Enumeration
{ String[] listOfFiles;
int current = 0;
ListOfFiles(String[] listOfFiles)
{ this.listOfFiles = listOfFiles;
}
public boolean hasMoreElements()
{ return current < listOfFiles.length;
}
public Object nextElement()
{ InputStream is = null;
if (!hasMoreElements())
throw new NoSuchElementException();
else
{ try
{ String next = listOfFiles[current++];
is = new FileInputStream(next);
}
catch (FileNotFoundException e) {}
}
return is;
}
}
Filterströme werden mit anderen Eingabeströmen verbunden, um die eingelesenen Daten weiterzubearbeiten.
Neben der Verwendung dieser Filter-Strom-Klassen aus der Bibliothek
besteht die Möglichkeit, eigene Filterklassen zu schreiben.
Benutzung am Beispiel von DataInputStream:
import java.io.*;
class CountLines
{
public static void main(String a[])
throws IOException
{ InputStream in;
if (a.length != 0)
in = new FileInputStream(a[0]);
else in = System.in;
DataInputStream dis =
new DataInputStream(in);
String inp;
int total = 0;
while (( inp = dis.readLine()) != null)
total++;
System.out.println("Number of lines: "
+ total);
}
}
DataInputStream liefert Einlesemethoden für alle gängigen Datentypen, u.a.:
Beispiel:
public class InFile extends DataInputStream
{ public InFile(String filename)
throws FileNotFoundException
{ super(
new BufferedInputStream(
new FileInputStream(filename)));
}
}
Beispiel:
import java.io.*;
class BinIO
{ public static void main(String[] args)
{ try
{ FileInputStream fis =
new FileInputStream("try.txt");
FileOutputStream fos =
new FileOutputStream("try_cp.txt");
int c;
while ((c = fis.read()) != -1)
{ fos.write(c);
}
fis.close();
fos.close();
}
catch (IOException e)
{ System.err.println("BinIO: " + e);
}
}
}
Die Klasse PrintStream liefert Methoden zur Ausgabe der textuellen Darstellung der Java-Grundtypen.
Da sie eher zur Zeichenausgabe (siehe Seite
) gehört,
wird die Klasse nicht mehr benutzt. Statt dessen kommt
die Klasse PrintWriter (siehe Seite
) zum Einsatz.
Einzige Bedeutung:
Die beiden Standard-Ausgabedateien System.out
und System.err sind vom Typ PrintStream.
Im Gegensatz zu den Byte-Strömen, die bis Java1.0 auch zur
Zeichenausgabe verwendet wurden, garantieren die Zeichen-Strom-Klassen
die korrekte Umsetzung von Unicode gemäß der lokalen
Gegebenheiten.
Zeichen-Strom-Eingabe wird von der abstrakten Klasse Reader realisiert:
import java.io.*;
public class ReadLines
{ public static void main (String a[])
{ BufferedReader din =
new BufferedReader(
new InputStreamReader(System.in));
String line;
do { try
{ line = din.readLine();
}
catch(IOException ioe)
{ break;
}
if (line == null) // end of stream
break;
System.out.println(line);
}
while (true);
}
}
Die Klasse StringReader bietet die Standard-Funktionalität der Reader-Klassen, wobei die Lesequelle ein String ist.
Beispiel:
import java.io.*;
class StrRead
{ public static void main(String[] a)
throws IOException
{ StringReader inp =
new StringReader(a[0]);
int c;
while((c = inp.read()) != -1)
System.out.println((char)c);
}
}
).
Beispiel:
import java.io.*;
class SquareList
{ public static void main(String[] a)
throws IOException
{ PrintWriter out =
new PrintWriter(
new BufferedWriter(
new FileWriter("square.list")));
for (int i = 0;
i < Integer.parseInt(a[0]);
i++)
{ out.print(i);
out.print(": ");
out.println(Math.sqrt(i));
}
out.close();
}
}
Ziel der RandomAccessFile-Klasse ist die freie Positionierung von Schreib-/Lese-Zeigern an beliebigen Datei-Positionen.
Beispiel:
import java.io.*;
class RandAcc
{ public static void main(String[] a)
throws IOException
{ RandomAccessFile rf;
rf = new RandomAccessFile(
"try.dat", "rw");
rf.writeChars("Jva");
rf.close();
rf = new RandomAccessFile(
"try.dat", "rw");
rf.seek(2); // Position 2
rf.writeChars("ava");
rf.close();
BufferedReader din =
new BufferedReader(
new FileReader("try.dat"));
// schreibe "Java":
System.out.println(din.readLine());
}
}
Die Klasse File bietet nützliche Methoden, um Datei- und Verzeichnisnamen zu manipulieren.
Außerdem erlauben viele der Konstruktoren der IO-Klassen ein
File-Argument:
File ipf = new File("input.dat");
FileInputStream fis =
new FileInputStream(ipf);
Einige nützliche Methoden
)
Beispiel: Löschen von Dateien
import java.io.*;
public class Delete // Lösche eine Datei
{ public static void main(String[] args)
{ try { delete(args[0]);}
catch (IllegalArgumentException e)
{ System.err.println(
e.getMessage() +": " + args[0]);
}
}
public static void delete(String name)
{ File f = new File(name);
if (!f.exists())
fail("No such file or directory");
if (!f.canWrite())
fail("Write protected");
if (f.isDirectory())
{ String[] files = f.list();
if (files.length > 0)
fail("Directory not empty");
}
if (!f.delete()) // jetzt endlich
fail("Deletion failed");
}
protected static void fail(String msg)
throws IllegalArgumentException
{ throw new IllegalArgumentException(msg);
}
}
Der StreamTokenizer erkennt 4 einfache Symbolklassen
und stellt deren Werte in öffentlichen Attributen zur Verfügung.
Kleines Beispiel:
static double sumStream(InputStream in)
throws IOException
{ StreamTokenizer nums =
new StreamTokenizer(in);
double result = 0.0;
while (nums.nextToken() ==
StreamTokenizer.TT_NUMBER)
result += nums.nval;
return result;
}
Serializable ist ein (``Marker''-) Interface in java.io, das dazu benutzt wird, Klassen zu kennzeichnen, von denen Objekte in Binärdateien abgelegt werden sollen (neu in Java1.1 ).
Serialisierung ist wichtig in Client/Server Anwendungen, für
Cut-and-Paste, für Software-Komponenten ( Beans)
und die Speicherung bereits initialisierter Applets.
Beispiel: Serialisierung von baumstrukturierten Objekten
Eine Klasse für Suchanfragen
Markiert als Serializable
import java.io.*;
abstract class SuchAnfrage
implements Serializable
{abstract public void print();
}
Ein einzelner Suchbegriff
import java.io.*;
public class Begriff extends SuchAnfrage
{ String begr;
Begriff(String b)
{ begr = b;
}
public void print()
{ System.out.print(begr + " ");
}
}
Und-Verknüpfung von Suchbegriffen
import java.io.*;
public class Und extends SuchAnfrage
{ SuchAnfrage sl;
SuchAnfrage sr;
public Und(SuchAnfrage sl,
SuchAnfrage sr)
{ this.sl = sl;
this.sr = sr;
}
public void print()
{ System.out.print("( ");
sl.print();
System.out.print("UND ");
sr.print();
System.out.print(") ");
}
}
Oder-Verknüpfung von Suchbegriffen
import java.io.*;
public class Oder extends SuchAnfrage
{ SuchAnfrage sl;
SuchAnfrage sr;
public Oder(SuchAnfrage sl,
SuchAnfrage sr)
{ this.sl = sl;
this.sr = sr;
}
public void print()
{ System.out.print("( ");
sl.print();
System.out.print("ODER ");
sr.print();
System.out.print(") ");
}
}
Negation von Suchbegriffen
import java.io.*;
public class Nicht extends SuchAnfrage
{ SuchAnfrage s;
Nicht(SuchAnfrage s)
{ this.s = s;
}
public void print()
{ System.out.print("NICHT ");
s.print();
}
}
Das Hauptprogramm: Serialisierung von Suchbegriffen
Zunächst wird eine Suchanfrage konstruiert:
(Java UND NICHT (C++ ODER Smalltalk))
import java.io.*;
public class Main
{ public static void main(String [] a)
throws IOException,
ClassNotFoundException
{ SuchAnfrage s;
s = new Und(
new Begriff("Java"),
new Nicht(
new Oder(
new Begriff("C++"),
new Begriff("Smalltalk")
)
)
);
// Objekte rausschreiben
ObjectOutputStream out =
new ObjectOutputStream(
new FileOutputStream("such.dat"));
out.writeObject(s);
out.close();
// Objekte einlesen
ObjectInputStream in =
new ObjectInputStream(
new FileInputStream("such.dat"));
SuchAnfrage wiederda =
(SuchAnfrage) in.readObject();
wiederda.print();
System.out.println();
}
}