Wie lässt sich ein Browserfenster aus Java heraus mit einer lokalen Seite oder einer Seite aus dem Internet öffnen? v.6.0

Die Java-Version 6.0 (oder 1.6) bietet mit der Klasse Desktop endlich eine simple Möglichkeit, ein Browser-Fenster zu öffnen um z.B. die Hilfe-Datei einer Application oder auch eine Webseite anzuzeigen.

Das Programmbeispiel besteht aus einem einfachen GUI mit zwei JButton die entweder eine lokale HTML-Seite oder eine Internetseite laden. Die Buttons werden bei einem ActionListener angemeldet, in dessen Methode actionPerformed(ActionEvent e) eine der beiden den Ladeprozess ausführenden Methoden aufgerufen wird.
Die Methode ladeINet(String seite) dient dazu, eine beliebige Webseite mit der Adresse seite zu laden. Dies geschieht durch die Methode browse(URI uri) der Klasse Desktop. Um ein Desktop-Objekt zu erhalten ruft man die statische Methode getDesktop() der Klasse Desktop auf.

Nicht ganz so trivial gestaltet sich der Aufruf einer lokalen Webseite. Die Ursache hierfür liegt darin, dass die anzuzeigende Seite möglicherweise ja mit dem Rest der Application in einer jar-Datei stecken könnte. Der Methode browse() muss wie o.a. ein URI als Parameter übergeben werden. Die Erzeugung eines URI mittels einer einfachen Pfadangabe liefert das Protokoll 'jar:', das ein Browser nicht interpretieren kann.
Ein Workaround besteht darin, die darzustellende Datei ins systemeigene temporäre Verzeichnis zu kopieren und von dort aus auszulesen. Die Methode ladeLocal(String seite) erledigt diese Aufgabe.

import java.awt.Desktop;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class BrowserOeffnen implements ActionListener {

    JButton localButt;
    JButton iNetButt;

    public BrowserOeffnen() {
        localButt = new JButton("local");
        localButt.addActionListener(this);
        iNetButt = new JButton("Inet");
        iNetButt.addActionListener(this);
        JFrame frame = new JFrame("Browser \u00f6ffnen");
        frame.setLayout(new FlowLayout());
        frame.add(localButt);
        frame.add(iNetButt);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    private void ladeINet(String seite) {
        try {
            Desktop.getDesktop().browse(new URI(seite));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

    private void ladeLocal(String seite) {
        File tmpIndexFile = null;
        StringBuffer sb = new StringBuffer();
        PrintWriter pWriter = null;
        try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(seite)) {
            if (is != null) {
                int b = 0;
                while ((b = is.read()) != -1) {
                    sb.append((char) b);
                }
                tmpIndexFile = File.createTempFile("javabeginners", ".htm");
                tmpIndexFile.deleteOnExit();
                if (tmpIndexFile.canWrite()) {
                    pWriter = new PrintWriter(tmpIndexFile);
                    pWriter.write(sb.toString());
                    pWriter.close();
                } else {
                    System.out.println("Tmp-File nicht beschreibbar");
                    return;
                }
                Desktop.getDesktop().browse(tmpIndexFile.toURI());

            } else {
                System.out.println("Laden nicht erfolgreich...");
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == localButt)
            ladeLocal("test.htm");
        if (e.getSource() == iNetButt)
            ladeINet("https://www.javabeginners.de");
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new BrowserOeffnen());
    }
}

Innerhalb eines try-catch-Blockes, der Fehler beim IO-Prozess abfängt wird zunächst ein InputStream mit Hilfe des ClassLoaders der aktuellen Klasse, bzw. dessen Methode getResourceAsStream(String name) erzeugt. Er zeigt auf den Pfad der auszulesenden Datei. Hier ist wichtig zu wissen, dass die Datei im Klassenpfad liegen muss. Dieser wird vom obersten package aus ermittelt. Da hier häufige Fehler liegen, hierzu ein Beispiel:
Im bin-Verzeichnis des Projektes befindet sich das package gui.frame mit der ausführenden Klasse 'Test.class' und ein Verzeichnis 'help' mit der anzuzeigenden Datei 'index.htm'.
In diesem Fall muss der Pfad help/index.htm angegeben werden.

-------- bin --------
 |              |
gui           help
 |              |
frame         index.htm
 |
Test.class

Innerhalb einer while-Schleife wird der Input-Stream ausgelesen. Dies geschieht in Form primitiver int-Werte, die in char gecastet und nacheinander in einen StringBuffer eingelesen werden.
Die Methode createTmpFile() der Klasse File erzeugt eine zunächst leere temporäre Datei im systemeigenen temporären Verzeichnis. Sie benötigt zwei String-Parameter: ein beliebiges Präfix und das Datei-Suffix mit Punkt. In diese wird der zum String gecastete StringBuffer mit Hilfe eines PrintWriter eingelesen. Hiermit ist der Kopiervorgang abgeschlossen und der Browser kann die temporäre Datei anzeigen.
Dies geschieht wie o.a. durch die Methode browse(), deren URI-Parameter über toURI() aus dem File-Objekt der temporären Datei erzeugt wird.

Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.