InputStream in URL umwandeln?

Arcaton

Mitglied
Hallo,

ich rufe eine Methode einer externen Libary auf, die als Parameter eine URL/URI auf eine Datei erwartet (in meinem Fall pdf-Files). Allerdings habe ich nur ein InputStream-Objekt zur Verfügung, welches die Datei enthält.

Ist es möglich mit einer URL auf einen Stream im Memory zu verweisen? Wann ja wie? Oder muss man den InputStream erst auf Platte speichern um darauf mit einer URL zu verweisen (was ich möglichst vermeiden möchte)?

Gruß,
Arcaton
 
Hallo,

welchen Datentyp besitzt der Parameter denn? Ist es einfach ein String mit der URL oder eine Instanz der Klasse java.net.URL?

Grüße,
Matthias
 

Arcaton

Mitglied
Hallo,

die Funktion, die ich nutzen will hat folgende Signatur:
Code:
public String extract(URI uri);

Jedoch habe ich kein URI-Objekt, sondern "nur" ein Objekt vom Typ InputStream. Wie kann ich der Funktion also den InputStream unterschieben?

Gruß,
Arcaton
 

flashray

Erfahrenes Mitglied
Hallo,

du könntest die Daten zunächst in eine temporäre Datei schreiben und von dort aus wieder lesen.

Java:
import java.io.*;
import java.net.URI;

public class TempFileDemo {

	public static void main(String args[]) throws IOException {
		File f = File.createTempFile("stream", ".tmp");
		URI u = f.toURI();

		String output = extract(u);

		System.out.println("Rückgabe von extract: ");
		System.out.println(output);
		System.out.println();

		FileInputStream fis = new FileInputStream(new File(u));
		BufferedInputStream bis = new BufferedInputStream(fis);

		System.out.println("Inhalt der temporären Datei: ");
		int i = 0;
		while ((i = bis.read()) != -1) {
			System.out.print((char) i);
		}

		// Löschen bei Programmende
		f.deleteOnExit();
	}

	public static String extract(URI uri) {
		String s = "Dies ist eine Zeile Text!";
		try {
			FileWriter fw = new FileWriter(new File(uri));
			fw.write(s);
			fw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return "Rückgabe";
	}
}


Vg Erdal
 

Arcaton

Mitglied
Hallo,

das schaut gut aus, so was hab ich gesucht, vielen vielen Dank für die Hilfe, werd ich mal ausprobieren. :)

Gruß,
Arcaton
 
Hallo,

eine Möglichkeit wäre, einen eigenen URL-Handler zu implementieren. Damit könnte man dann eine URI mit dem Schema „inputstream://id“ verwenden, die der eigene URL-Handler dann behandelt. Die id könnte sich beispielsweise dadurch ergeben, dass man den InputStream in einen Vector steckt, wobei id dann den jeweiligen Index darstellt. Ich hätte gerade eine kleine Beispielimplementation geschrieben. Wenn du willst, kann ich die mal halbwegs präsentierfertig machen und reinstellen.

Grüße,
Matthias
 

Arcaton

Mitglied
Hallo,

die Variante mit dem URL-Handler wäre eleganter, da ich so den Stream nicht auf der Platte "parken" müsste. Für ein paar Code-Schnipsel wäre ich dankbar, es muss nicht komplett sein, nur grob das ich vielleicht ein paar Anhaltpunkte habe.

Gruß,
Arcaton
 

Thomas Darimont

Erfahrenes Mitglied
Hallo!

Interessante Idee :)
Das könnte beispielsweise wie folgt aussehen:
Unser inputstream Protocol Handler:
Java:
/**
 * 
 */
package de.tutorials.protocol.inputstream;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.Map;

/**
 * @author Tom
 * 
 */
public class Handler extends URLStreamHandler {
    protected URLConnection openConnection(URL u) throws IOException {
        return new InputStreamURLConnection(u);
    }

    static class InputStreamURLConnection extends URLConnection {

        public InputStreamURLConnection(URL url) {
            super(url);
        }

        public void connect() throws IOException {

        }

        public InputStream getInputStream() throws IOException {
            InputStream inputStream = extractInputStream(getURL().getHost(),
                    getURL().getFile().substring(1));
            return inputStream;
        }

        /**
         * @param fullyQualifiedFieldName
         * @param inputStreamID
         * @return
         * @throws IOException
         */
        private InputStream extractInputStream(String fullyQualifiedFieldName,
                String inputStreamID) throws IOException {
            String className = fullyQualifiedFieldName.substring(0,
                    fullyQualifiedFieldName.lastIndexOf('.'));
            String fieldName = fullyQualifiedFieldName
                    .substring(fullyQualifiedFieldName.lastIndexOf('.') + 1);

            InputStream inputStream = null;
            try {
                Class clazz = Class.forName(className);
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                Map map = (Map) field.get(null);
                inputStream = (InputStream) map.get(inputStreamID);
            } catch (Exception e) {
                throw new IOException(e);
            }

            return inputStream;
        }
    }
}

Und so wirds benutzt:
Java:
/**
 * 
 */
package de.tutorials;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Tom
 * 
 */
public class CustomURLStreamHandlerExample {

    final static Map<String, InputStream> MAP = new HashMap<String, InputStream>();

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.setProperty("java.protocol.handler.pkgs",
                "de.tutorials.protocol");

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
                "www.tutorials.de".getBytes());
        MAP.put("testStream", byteArrayInputStream);

        try {
            URL url = new URL(
                    "inputstream://de.tutorials.CustomURLStreamHandlerExample.MAP/testStream");

            InputStream inputStream = url.openStream();
            byte[] buffer = new byte[1024];
            int bytesRead = 0;
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            while ((bytesRead = inputStream.read(buffer)) > 0) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
            }

            System.out.println(new String(byteArrayOutputStream.toByteArray()));

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Man muss hier nur beachten die Resourcen später auch wieder entsprechend freizugeben...

Gruß Tom
 

kleopatra

Grünschnabel
cool - funktioniert, danke :)

Gibt's da mitlerweile eine im jdk eingebaute Option? Eigentlich ist eine URL auf in-memory Daten ja nicht sooo ungewöhnlich ..