84

I have a method which expects the one of the input variable to be of java.io.File type but what I get is only InputStream. Also, I cannot change the signature of the method.

How can I convert the InputStream into File type with out actually writing the file on to the filesystem?

Renato Back
  • 636
  • 1
  • 9
  • 20
Ram
  • 2,864
  • 10
  • 37
  • 44

2 Answers2

128

Something like this should work. Note that for simplicity, I've used a Java 7 feature (try block with closeable resource), and IOUtils from Apache commons-io. If you can't use those it'll be a little longer, but the same idea.

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
  • 1,840
  • 1
  • 16
  • 16
  • 8
    Isn't createTempFile actually does write a real file, that you can see in the file-system? – android developer Apr 11 '16 at 13:57
  • you are technically correct. using the code above, the temp file will exist until the program exits or it is deleted by the program. – cobbzilla Apr 21 '16 at 02:07
  • The docs of deleteOnExit say you shouldn't rely on it to work (and I think it actually doesn't even do anything) : http://developer.android.com/reference/java/io/File.html#deleteOnExit() . In addition, if you know how to stream the audio into playing, without any file, please write about it here: http://stackoverflow.com/q/36552381/878126 – android developer Apr 21 '16 at 05:24
  • 4
    Generally speaking, I prefer for the application to delete the temp file when it makes sense to do so. I use `deleteOnExit` as an extra sanity-check, never relying on it unconditionally. I know that in certain situations (`kill -9` the JVM, for example) the shutdown hooks that perform the deletion will never get called. – cobbzilla Jul 29 '16 at 00:15
  • If you're using this on Android, add ```implementation 'org.apache.directory.studio:org.apache.commons.io:2.4'``` to gradle. – LordParsley Mar 20 '18 at 11:01
  • If you are using Spring framework, you could use its `FileCopyUtils.copy(..)` instead of `IOUtils.copy(..)` – Afshar Jan 09 '21 at 08:57
  • `IOUtils` is deprecated – abdulwasey20 Feb 25 '21 at 07:59
31

You can't. The input stream is just a generic stream of data and there is no guarantee that it actually originates from a File. If someone created an InputStream from reading a web service or just converted a String into an InputStream, there would be no way to link this to a file. So the only thing you can do is actually write data from the stream to a temporary file (e.g. using the File.createTempFile method) and feed this file into your method.

Jan Thomä
  • 12,855
  • 5
  • 52
  • 81
  • 8
    Indeed, the [`File#createTempFile()`](http://download.oracle.com/javase/6/docs/api/java/io/File.html#createTempFile%28java.lang.String,%20java.lang.String%29) is really your best bet. – BalusC Nov 30 '10 at 18:23
  • 8
    Also see [`File#deleteOnExit()`](http://download.oracle.com/javase/6/docs/api/java/io/File.html#deleteOnExit%28%29), which causes the JVM to attempt to delete the file automatically when the JVM exits. Of course it's best to delete the temp file manually and immediately, once you know the file is no longer needed and no longer in use. But in an imperfect world sometimes imperfect solutions are necessary. – Mike Clark Nov 30 '10 at 18:43