next up previous contents index
Nächste Seite: Grafische Benutzungsschnittstellen Aufwärts: Programmieren in Java Vorherige Seite: Parallelausführung   Inhalt   Index

Unterabschnitte

Ein-/Ausgabe

Ein- und Ausgabe ist im Paket java.io implementiert. Die gliedert sich in die Hauptbereiche



\psfig {figure=bilder/ioover.ps}




Die Klassen aus java.io benutzt man meist nicht einzeln sondern in Kombination.




Byte-Ströme

Byte-Ströme dienen zur Speicherung binärer Daten

Binäre Eingabe-Ströme

Byte-Strom-Eingabe wird von der abstrakten Klasse InputStream realisiert:



\psfig {figure=bilder/ioistr.ps}


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:




Folgen von Eingabeströmen



SequenceInputStream wird verwendet um ein Folge von Eingabeströmen zu verarbeiten:


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



Gefilterte Binär-Eingabe

Filterströme werden mit anderen Eingabeströmen verbunden, um die eingelesenen Daten weiterzubearbeiten.

\psfig {figure=bilder/iofistr.ps}

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.:




\psfig {figure=bilder/methind.ps}

public final byte readByte();
public final char readChar();
public final double readDouble();
public final float readFloat();
public final int readInt();
public final String readLine();
public final long readLong();
public final short readShort();


Gepufferte Binär-Eingabe

Die Klasse BufferedInputStream steigert die Effizienz der Eingabe, indem größere Datenmenge in einem internen Puffer zwischengespeichert werden.



Beispiel:




public class InFile extends DataInputStream 
{ public InFile(String filename)
  throws FileNotFoundException 
  { super(
      new BufferedInputStream(
        new FileInputStream(filename)));
  }
}


Binäre Ausgabe-Ströme

Byte-Strom-Ausgabe wird von der abstrakten Klasse OutputStream realisiert:

\psfig {figure=bilder/ioostr.ps}


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



Ausgabe textueller Darstellung der Grundtypen

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.



Zeichen-Ströme

Zeichen-Ströme dienen zur Speicherung von Texten. Sie wurden in Java1.1 eingeführt.



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-Eingabe-Ströme

Zeichen-Strom-Eingabe wird von der abstrakten Klasse Reader realisiert:



\psfig {figure=bilder/ioread.ps}


Anwendung: Gepufferte Texteingabe


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


Anwendung: Texteingabe aus Strings

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




Zeichen-Ausgabe-Ströme

Zeichen-Strom-Ausgabe wird von der abstrakten Klasse Writer realisiert:



\psfig {figure=bilder/iowrite.ps}



Gepufferte Zeichenausgabe für die Grundtypen

Die Klasse PrintWriter bietet Methoden für die Zeichenausgabe der Java-Grundtypen. Sie ersetzt in Java1.1 die Klasse PrintStream (siehe Seite [*]).



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



Random Access Dateien

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



Datei- und Verzeichnis-Namen

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




\psfig {figure=bilder/methind.ps}

boolean delete()

boolean exists()

boolean isDirectory()

boolean isFile()

long length()

String[] list()

String [] list(FilenameFilter) (z.B.: Seite [*])

boolean mkdir()

boolean renameTo(File)


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


Zerlegung von Strömen in Einzelsymbole

Mit StreamTokenizer bietet Java eine Klasse für einfache Zerlegung von Eingabeströmen in Einzelsymbole.



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



Ausgabe von Objekten (Serialisierung)

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



next up previous contents index
Nächste Seite: Grafische Benutzungsschnittstellen Aufwärts: Programmieren in Java Vorherige Seite: Parallelausführung   Inhalt   Index
Peter Pfahler, 1997