Cómo convertir InputStream a archivo virtual


81

Tengo un método que espera que la variable de entrada sea del tipo java.io.File, pero lo que obtengo es solo InputStream. Además, no puedo cambiar la firma del método.

¿Cómo puedo convertir InputStream en un tipo de archivo sin tener que escribir el archivo en el sistema de archivos?


¿Es esta una función incorporada? o es una función personalizada?
Richard J. Ross III

2
@Richard: "No puedo cambiar la firma del método".
BalusC

¿Por qué exactamente necesitas un Fileobjeto en lugar de InputStream?
Poindexter

2
No puedo usar InputStream porque la API que estoy usando mandatos Archivo
Ram

Me parece que alguien diseñó una API rota que solo acepta archivos en lugar de InputStreams, y ahora tienes que usar esta API
Mike76

Respuestas:


121

Algo como esto debería funcionar. Tenga en cuenta que para simplificar, he usado una función de Java 7 (intente bloquear con recurso que se puede cerrar) e IOUtils de Apache commons-io. Si no puede usarlos, será un poco más largo, pero la misma 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;
    }

}

8
¿No es createTempFile realmente escribe un archivo real, que puede ver en el sistema de archivos?
desarrollador de Android

es técnicamente correcto. usando el código anterior, el archivo temporal existirá hasta que el programa salga o sea eliminado por el programa.
cobbzilla

Los documentos de deleteOnSalir dicen que no debes confiar en que funcione (y creo que en realidad ni siquiera hace nada): developer.android.com/reference/java/io/… . Además, si sabe cómo transmitir el audio a la reproducción, sin ningún archivo, escríbalo aquí: stackoverflow.com/q/36552381/878126
desarrollador de Android

4
En términos generales, prefiero que la aplicación elimine el archivo temporal cuando tenga sentido hacerlo. Lo uso deleteOnExitcomo un control adicional de cordura, nunca confío incondicionalmente en él. Sé que en ciertas situaciones ( kill -9la JVM, por ejemplo) nunca se llamará a los ganchos de cierre que realizan la eliminación.
cobbzilla

Si está usando esto en Android, agréguelo implementation 'org.apache.directory.studio:org.apache.commons.io:2.4'a gradle.
LordParsley

30

No puedes. El flujo de entrada es solo un flujo genérico de datos y no hay garantía de que realmente se origine en un archivo. Si alguien crea un InputStream a partir de la lectura de un servicio web o simplemente convierte un String en un InputStream, no habría forma de vincularlo a un archivo. Entonces, lo único que puede hacer es escribir datos de la secuencia en un archivo temporal (por ejemplo, usando el método File.createTempFile) e introducir este archivo en su método.


7
De hecho, File#createTempFile()es realmente tu mejor opción.
BalusC

7
Consulte también File#deleteOnExit(), lo que hace que la JVM intente eliminar el archivo automáticamente cuando sale de la JVM. Por supuesto, es mejor eliminar el archivo temporal de forma manual e inmediata, una vez que sepa que el archivo ya no es necesario y ya no está en uso. Pero en un mundo imperfecto a veces se necesitan soluciones imperfectas.
Mike Clark
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.