So konvertieren Sie InputStream in eine virtuelle Datei

81

Ich habe eine Methode, die erwartet, dass die Eingabevariable vom Typ java.io.File ist, aber ich erhalte nur InputStream. Außerdem kann ich die Signatur der Methode nicht ändern.

Wie kann ich den InputStream in einen Dateityp konvertieren, ohne die Datei tatsächlich in das Dateisystem zu schreiben?

RAM
quelle
Ist das eine eingebaute Funktion? oder ist es eine benutzerdefinierte Funktion?
Richard J. Ross III
2
@ Richard: "Ich kann die Signatur der Methode nicht ändern."
BalusC
Warum genau benötigen Sie ein FileObjekt anstelle des InputStream?
Poindexter
2
Ich kann InputStream nicht verwenden, da die von mir verwendete API die Datei File
Ram
Mir scheint, dass jemand eine kaputte API entworfen hat, die nur Dateien anstelle von InputStreams akzeptiert, und jetzt müssen Sie diese API verwenden
Mike76

Antworten:

121

So etwas sollte funktionieren. Beachten Sie, dass ich der Einfachheit halber eine Java 7-Funktion (Block mit verschließbarer Ressource versuchen) und IOUtils von Apache commons-io verwendet habe. Wenn Sie diese nicht verwenden können, dauert es etwas länger, aber die gleiche Idee.

import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class StreamUtil {

    public static final String PREFIX = "stream2file";
    public static final String SUFFIX = ".tmp";

    public static File stream2file (InputStream in) throws IOException {
        final File tempFile = File.createTempFile(PREFIX, SUFFIX);
        tempFile.deleteOnExit();
        try (FileOutputStream out = new FileOutputStream(tempFile)) {
            IOUtils.copy(in, out);
        }
        return tempFile;
    }

}
Cobbzilla
quelle
8
Schreibt createTempFile nicht tatsächlich eine echte Datei, die Sie im Dateisystem sehen können?
Android-Entwickler
Sie sind technisch korrekt. Mit dem obigen Code bleibt die temporäre Datei bestehen, bis das Programm beendet oder vom Programm gelöscht wird.
Cobbzilla
In den Dokumenten von deleteOnExit heißt es, Sie sollten sich nicht darauf verlassen, dass es funktioniert (und ich denke, es macht eigentlich gar nichts): developer.android.com/reference/java/io/… . Wenn Sie wissen, wie Sie Audio ohne Datei in die Wiedergabe streamen können, schreiben Sie bitte hier darüber: stackoverflow.com/q/36552381/878126
Android-Entwickler
4
Im Allgemeinen bevorzuge ich, dass die Anwendung die temporäre Datei löscht, wenn dies sinnvoll ist. Ich benutze es deleteOnExitals zusätzlichen Gesundheitscheck und verlasse mich nie bedingungslos darauf. Ich weiß, dass in bestimmten Situationen ( kill -9z. B. der JVM) die Shutdown-Hooks, die das Löschen durchführen, niemals aufgerufen werden.
Cobbzilla
Wenn Sie dies unter Android verwenden, fügen Sie es implementation 'org.apache.directory.studio:org.apache.commons.io:2.4'zu gradle hinzu.
LordParsley
30

Das kannst du nicht. Der Eingabestream ist nur ein generischer Datenstrom und es gibt keine Garantie dafür, dass er tatsächlich aus einer Datei stammt. Wenn jemand einen InputStream aus dem Lesen eines Webdienstes erstellt oder nur einen String in einen InputStream konvertiert hat, gibt es keine Möglichkeit, diesen mit einer Datei zu verknüpfen. Sie können also nur Daten aus dem Stream in eine temporäre Datei schreiben (z. B. mithilfe der File.createTempFile-Methode) und diese Datei in Ihre Methode einspeisen.

Jan Thomä
quelle
7
In der Tat ist das File#createTempFile()wirklich Ihre beste Wahl.
BalusC
7
Siehe auch File#deleteOnExit(), wodurch die JVM versucht, die Datei beim Beenden der JVM automatisch zu löschen. Natürlich ist es am besten, die temporäre Datei manuell und sofort zu löschen, sobald Sie wissen, dass die Datei nicht mehr benötigt wird und nicht mehr verwendet wird. Aber in einer unvollkommenen Welt sind manchmal unvollkommene Lösungen notwendig.
Mike Clark