Java InputStream zweimal lesen

InputStream zweimal lesen

Einen InputStream kann man in Java nur einmal lesen - und eben nicht öfters nutzen. Wer einen InputStream zweimal lesen will (oder häufiger), muss etwas tricksen. Das kann beispielsweise notwendig werden, wenn man einen eingehenden Request zunächst protokollieren und dann an einen XML Parser übergeben will.

Da wir ein und den selben InputStream nicht zweimal lesen können, müssen wir uns eben einen zweiten InputStream erschaffen. Am einfachsten geht das, indem man den Inhalt des ersten Streams in ein Byte-Array puffert und sich daraus je nach Bedarf so viele neue InputStreams erzeugt, wie man will.
Diese einfache Vorgehensweise setzt natürlich voraus, dass der gesamte Datenstrom auch wirklich im Hauptspeicher gehalten werden kann. Da dies in der Praxis fast immer der Fall sein wird, wollen wir auf diese Einschränkung nicht näher eingehen.

Beispiel: Java InputStream zweimal lesen oder sogar noch öfters

Die folgende Funktion puffert die Daten aus einem InputStream in ein byte-Array und erzeugt danach aus eben diesem byte-Array so viele neue InputStream-Objekte wie gewünscht, so dass die selben Daten mehrfach gelesen werden. Dazu wird die Funktion toByteArray verwendet, die wir noch implementieren müssen, was wir weiter unten gleich tun werden.


    /**
     * Verarbeitet die Daten eines Streams mehrfach.
     * Dabei wollen wir den InputStream zweimal lesen (oder häufiger).
     */
    public void processRequest(final InputStream is) throws Exception {
        final byte[] requestData = toByteArray(req.getInputStream()); // Daten aus dem InputStream werden hier gepuffert!
        // Jetzt können wir aus diesem Puffer soviele InputStreams erzeugen, wie wir wollen:
        processRequestData(new java.io.ByteArrayInputStream(requestData)); // verarbeitet den Stream...
        processRequestData(new java.io.ByteArrayInputStream(requestData)); // verarbeitet den Stream nochmal...
        // wenn wir den InputStream mehr als zweimal lesen wollen:
        processRequestData(new java.io.ByteArrayInputStream(requestData)); // verarbeitet den Stream ein drittes mal.
    }

Das "Geheimnis" ist bislang noch die ominöse Methode toByteArray, die aber sehr einfach zu implementieren ist:


    /**
     * Konvertiert einen InputStream in ein byte-Array.
     * Der Zweck davon ist, dass aus diesem byte-Array jederzeit ein neuer InputStream erzeugt werden kann.
     * So kann man die Daten aus dem InputStream zweimal lesen.
     */
    private static byte[] toByteArray(final java.io.InputStream is) throws java.io.IOException {
        final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        final byte[] block = new byte[4096]; // verarbeite 4k-Blöcke, geht schneller als einzelne Bytes
        int count;
        while ((count = is.read(block)) > 0) {
            outStream.write(block, 0, count);
        }
        outStream.close();
        return outStream.toByteArray();
    }

Damit haben wir es geschafft: wir können einen InputStream zweimal lesen - oder dreimal oder noch öfter. Genau genommen natürlich nicht ein und den selben InputStream, sondern immer neue InputStreams, welche aber immer den jeweils selben Datenstrom liefern - so oft wir wollen.



Nach oben, Inhaltsverzeichnis, Impressum Admin: Artikel editieren