3 Häufig gepostete Fragen

3.1 [LANG] Die Sprache Java

3.2 [STRING] Strings

3.3 [IO] Eingabe/Ausgabe, Streams, etc.

3.4 [NET] Netzwerk

3.5 [AWT] Abstract Window Toolkit

3.6 [SWING] Swing, das bevorzugte GUI

3.7 [APPLET] Java-Applets und ihre Zusammenarbeit mit Browsern

3.8 [SERVER] Servlets und andere Server-Implementierungen in Java

3.9 [NONCORE] Klassen/Packages, die über den Kern der Sprache hinausgehen, also Java3D etc.

3.10 [OOP] OOP-Konzepte und Patterns in Java

3.11 [JDK] Virtuelle Maschinen, alles über JDKs und deren Installation und Verwendung

3.12 [TOOLS] Java-Zusatz-Tool, zum Beispiel IDEs, Build-Tools, Profiler, etc.

3.13 [MISC] Alles, was nicht in eine der anderen Rubriken paßt

3.14 [ERROR] Fehlermeldungen


3.3 [IO] Eingabe/Ausgabe, Streams, etc.

Zurück zu "3 Häufig gepostete Fragen"

3.3.1 Verlangsamt Serialisierung mein Programm?

Java bietet mit dem Mechanismus der Serialisierung auf einfache Weise die Möglichkeit, den aktuellen Zustand des Objekts auf einem Datenträger, das Netz oder sonst wohin über einen Stream zu sichern. Der verwendete Mechanismus ist relativ kompliziert, damit auch alle auftretenden Möglichkeiten korrekt behandelt werden können. Sind die Daten der Objekte sehr groß, so empfiehlt es sich, eigene Prozeduren zur Speicherung zu entwickeln, die dann nicht mehr allgemeingültig, aber auf die aktuelle Verwendung angepaßt und damit schneller sind.

Autor: Markus Reitz

Zurück zu "3.3 [IO] Eingabe/Ausgabe, Streams, etc."

3.3.2 Wie kann ich rekursiv einen Verzeichnisbaum abarbeiten?

In java.io.File befinden sich die dazu benötigte Funktionalität. Mit list() läßt man sich ein Array mit allen Dateinamen geben, mit isDirectory() läßt sich prüfen, ob es sich bei dem File-Objekt um ein Verzeichnis handelt. Indem man nun rekursiv in Unterverzeichnisse absteigt, kann man so einen kompletten Verzeichnisbaum abarbeiten.

Hier ein Beispielprogramm (scantree.java):

import java.io.File;

public class scantree {
    public static void main(String[] args) {
        // Programm muss einen Verzeichnisnamen als Parameter haben
        File dir = new File(args[0]);
        scan(dir);
    }

    public static void scan(File dir) {
        // Liste aller Dateien und Unterverzeichnisse holen
        String[] entries = dir.list();
        if (entries == null || entries.length < 1) {
            return;
        }
        for (int i = 0; i < entries.length; i++) {
            File entry = new File(dir, entries[i]);
            if (entry.isDirectory()) {
                scan(entry); // rekursiv ins Unterverzeichnis verzweigen
            } else {
                // entry ist eine Datei
                System.out.println(entry);
            }
        }
    }
}

Autor: Marco Schmidt

Zurück zu "3.3 [IO] Eingabe/Ausgabe, Streams, etc."

3.3.3 Wie kann ich aus Dateien zeilenweise lesen?

Generell nutzt man für die Datei-Operationen einen Buffered Reader oder eine Klasse, die von dieser abstammt. Diese Klasse besitzt dann die Methode readLine(), die eine Zeile aus der Datei ausliest und diese Zeile als einen String zurückgibt.

Zu beachten ist, daß bei Erreichen des Dateiendes kein leerer String, sondern eine Nullreferenz zurückgegeben wird. Ein Programm, daß aus einer Datei zeilenweise liest, sieht in Java wie folgt aus:

import java.io.*;

public class ZeilenWeiseLesen {
    public static void main(String[] args) {
        try {
            String zeile;

            //Wir lesen aus "eingabe.txt".
            File eingabeDatei = new File("eingabe.txt");
            FileReader eingabeStrom = new FileReader(eingabeDatei);
            BufferedReader eingabe = new BufferedReader(eingabeStrom);

            while ((zeile = Eingabe.readLine()) != null) {
                System.out.println(Zeile);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Autor: Markus Reitz

Zurück zu "3.3 [IO] Eingabe/Ausgabe, Streams, etc."

3.3.4 Wie kann ich Exponentialzahlen (z.B. 1.09E+008) aus einer Datei lesen?

Mit Java führt folgendes Verfahren zum Ziel: Lies die Daten als Strings ein und wandel sie mittels Double.valueOf(my_string).doubleValue() in einen double Wert um.

Das StreamTokenizer keine Exponentialzahlen kennt hat von Sun Bug Status bekommen (obgleich der StreamTokenizer so arbeitet wie angegeben):

Der Sun Workaround soll wohl ein:

    public void parseExponentialNumbers(boolean flag)

sein.

Beispiel:

import java.io.*;
import java.util.Vector;
/**
 * @author Wolfram Rühaak
 * Beispielcode, der zeigt wie man Zahlen aus einer Datei liest.
 * Die Datei darf in diesem Fall nur Zahlen enthalten, getrennt durch
 * Tabulator oder Space.
 * Die Anzahl von Spalten/Zeilen ist nicht vorgegeben.
 * Um *.cvs Kompatibilät zu erhalten kann man als whitespaceChars
 * noch ',' und ';' hinzufügen.
 */
public class ReadExponential {

    int ni; // Anzahl Zeilen
    int nj; // Anzahl Spalten

     private ReadExponential(String Filename) {
         int i=0;
         int j=0;
         Vector v2 = new Vector();

         try {
             FileInputStream fis = new FileInputStream(Filename);
             BufferedReader r =
                     new BufferedReader(new InputStreamReader(fis));
             StreamTokenizer st  = new StreamTokenizer(r);
             /*
              * Nachfolgendes Code-Fragment von:
              * Mark Gritter ([email protected])
              * Betrifft:Re: This is easy in C++ (asking for help)
              * Newsgroups:comp.lang.java.programmer
              * Datum:1997/11/07
              */
             st.resetSyntax();
             st.whitespaceChars(' ', ' ');
             st.whitespaceChars('\n', '\n');
             st.wordChars('0','9');
             st.wordChars('e','e');
             st.wordChars('E','E');
             st.wordChars('.','.');
             st.wordChars('+','+');
             st.wordChars('-','-');
             /* Ende Code-Fragment */
            st.eolIsSignificant(true);

            try {
                while(st.nextToken() != st.TT_EOF) {
                    String s1 = st.sval;
                    if(s1!=null) {
                        // Wert in Vector schreiben
                        v2.addElement(s1);
                        // Anzahl von Zeilen
                        i=st.lineno();
                    }
                }
            } catch(IOException ioe) {}
        } catch (FileNotFoundException fnfe) {}
        ni = i - 1;
        nj = ((v2.size())/(ni+1))-1;   // Anzahl von Spalten berechnen

        double[][] dAllValues = new double [ni+1][nj+1];
        int k=0;
        for(i = 0;i <= ni; i++) {
            for(j = 0;j <= nj; j++) {
                Object f = v2.elementAt(k); // Vector in
                String s = f.toString();    // Array umspeichern
                /*
                 * Double.valueOf(String s) kann jeden numerischen Wert
                 * von String nach double umwandeln
                 */
                dAllValues[i][j] = Double.valueOf(s).doubleValue();
                k++;
            }
        }
    }
}

Autor: Wolfram Rühaak

Zurück zu "3.3 [IO] Eingabe/Ausgabe, Streams, etc."

3.3.5 Wie kann ich mit Java Dateien kopieren?

Bestimmt die performanteste Lösung wäre, mit

 System.exec(...)

die Aufgabe dem Betriebssystem zu übergeben.

Der Nachteil ist hier, dass so schwer ein plattformunabhängiger Code erreichbar ist und die Fehlerbehandlung schwierig wird.

Deshalb einfach eine Datei lesen und in eine andere, neue Datei schreiben, z.B. so:

import java.io.*;

public static void copyFile(File src, File dest, int bufSize,
        boolean force) throws IOException {
    if(dest.exists()) {
        if(force) {
            dest.delete();
        } else {
            throw new IOException(
                    "Cannot overwrite existing file: " + destName);
        }
    }
    byte[] buffer = new byte[bufSize];
    int read = 0;
    InputStream in = null;
    OutputStream out = null;
    try {
        in = new FileInputStream(src);
        out = new FileOutputStream(dest);
        while(true) {
            read = in.read(buffer);
            if (read == -1) {
                //-1 bedeutet EOF
                break;
            }
            out.write(buffer, 0, read);
        }
    } finally {
        // Sicherstellen, dass die Streams auch
        // bei einem throw geschlossen werden.
        // Falls in null ist, ist out auch null!
        if (in != null) {
            //Falls tatsächlich in.close() und out.close()
            //Exceptions werfen, die jenige von 'out' geworfen wird.
            try {
                in.close();
            }
            finally {
                if (out != null) {
                    out.close();
                }
            }
        }
    }
}

Das schwierigste ist hier wohl die Fehlerbehandlung, die je nach Anforderung unterschiedlich sein kann.

Anmerkung: Ein paar exotische VMs optimieren read(byte[]) bzw. write(byte[]) nicht, so dass hier ein BufferedInputStream oder BufferedOutputStream evtl. angebracht ist.

Autor: Martin Erren, Uwe Günther, Ulf Jährig, Christian Kaufhold

Zurück zu "3.3 [IO] Eingabe/Ausgabe, Streams, etc."

3.3.6 Wie kann man auf programmnahe Resourcen (Button-images, local String properties,...) zugreifen, ohne absolut oder relativ zu user.dir adressieren zu müssen (ich will das ganze auch in ein jar packen können)?

    URL Class#getResource(String)

und

    InputStream Class#getResourceAsStream(String)

sind Deine Freunde. Laut API-doc ist "/img.jpg" relativ zur codeBase, also dem aktuellen Eintrag im CLASSPATH, wo Deine Klasse geladen wurde, und "img.jpg" relativ zur Klasse, also im selben Verzeichnis, wo auch die Klasse liegt.

Ob Applikation oder Applet, *.jar oder file-system spielt hier keine Rolle.

mit

    System.out.println(MyClass.class.getResource("/").toString());

kannst Du jederzeit feststellen, welche codebase die jeweilige Klasse hat.

Weiterhin sind

    InputStream ClassLoader.getSystemResourceAsStream(name);

und

    URL ClassLoader.getSystemResource(name)

für eigene Resourcen nicht zu empfehlen.

[Hier fehlt die Begründung]

Autor: Martin Erren

Zurück zu "3.3 [IO] Eingabe/Ausgabe, Streams, etc."
Hosted by www.Geocities.ws

1