Як конвертувати InputStream у віртуальний файл


82

У мене є метод, який передбачає, що одна із вхідних змінних має тип java.io.File, але я отримую лише InputStream. Крім того, я не можу змінити підпис методу.

Як я можу перетворити InputStream у тип файлу без фактичного запису файлу у файлову систему?


Це вбудована функція? чи це нестандартна функція?
Річард Дж. Росс III

2
@Richard: "Я не можу змінити підпис методу."
BalusC

Навіщо саме вам потрібен Fileоб’єкт замість InputStream?
Poindexter

2
Я не можу використовувати InputStream, оскільки API, який я використовую, наказує Файл
Ram

Мені здається, хтось розробив непрацюючий API, який приймає лише файли замість InputStreams, і тепер вам доведеться використовувати цей API
Mike76,

Відповіді:


123

Щось подібне мало би спрацювати. Зверніть увагу, що для простоти я використовував функцію Java 7 (спробуйте заблокувати із закритим ресурсом) та IOUtils від Apache commons-io. Якщо ви не можете використовувати їх, це буде трохи довше, але така ж ідея.

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
Хіба createTempFile насправді не пише реальний файл, який ви можете побачити у файловій системі?
розробник android

ви технічно правильні. використовуючи наведений вище код, тимчасовий файл буде існувати до виходу програми або її видалення програмою.
cobbzilla

У документах deleteOnExit сказано, що вам не слід покладатися на це для роботи (і я думаю, що насправді навіть нічого не робить): developer.android.com/reference/java/io/… . Окрім того, якщо ви знаєте, як транслювати звук у програвання без будь-якого файлу, напишіть про це тут: stackoverflow.com/q/36552381/878126
розробник Android

4
Взагалі кажучи, я вважаю за краще, щоб програма видаляла тимчасовий файл, коли має сенс це робити. Я використовую deleteOnExitяк додаткову перевірку осудності, ніколи не покладаючись на це беззастережно. Я знаю, що в певних ситуаціях (наприклад, kill -9JVM) гачки вимкнення, які виконують видалення, ніколи не викликатимуться.
cobbzilla

Якщо ви використовуєте це на Android, додайте implementation 'org.apache.directory.studio:org.apache.commons.io:2.4'до gradle.
LordParsley 20.03.18

30

Ви не можете. Вхідний потік - це лише загальний потік даних, і немає гарантії, що він насправді походить із файлу. Якби хтось створив InputStream із читання веб-служби або просто перетворив String у InputStream, не було б можливості зв’язати це з файлом. Отже, єдине, що ви можете зробити, це фактично записати дані з потоку у тимчасовий файл (наприклад, за допомогою методу File.createTempFile) та подати цей файл у свій метод.


8
Справді, File#createTempFile()це справді найкращий ваш вибір.
BalusC

7
Також див. File#deleteOnExit(), Що змушує JVM намагатися автоматично видалити файл при виході JVM. Звичайно, найкраще видалити тимчасовий файл вручну і негайно, як тільки ви дізнаєтесь, що файл більше не потрібний і не використовується. Але в недосконалому світі часом потрібні недосконалі рішення.
Mike Clark
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.