Cách chuyển InputStream thành tệp ảo


81

Tôi có một phương thức mong đợi một trong các biến đầu vào thuộc loại java.io.File nhưng những gì tôi nhận được chỉ là InputStream. Ngoài ra, tôi không thể thay đổi chữ ký của phương thức.

Làm cách nào để chuyển đổi InputStream thành Loại tệp mà không thực sự ghi tệp vào hệ thống tệp?


Đây có phải là một chức năng tích hợp sẵn không? hay nó là một chức năng tùy chỉnh?
Richard J. Ross III,

2
@Richard: "Tôi không thể thay đổi chữ ký của phương thức."
BalusC

Chính xác thì tại sao bạn cần một Fileđối tượng thay vì InputStream?
Poindexter

2
Tôi không thể sử dụng InputStream vì API Tôi đang sử dụng nhiệm vụ tập tin
Ram

Dường như với tôi rằng ai đó đã thiết kế một API vỡ mà chỉ chấp nhận những file thay vì InputStreams, và bây giờ bạn phải sử dụng API này
Mike76

Câu trả lời:


121

Một cái gì đó như thế này sẽ hoạt động. Lưu ý rằng để đơn giản hơn, tôi đã sử dụng một tính năng Java 7 (thử khối với tài nguyên có thể đóng được) và IOUtils từ Apache commons-io. Nếu bạn không thể sử dụng chúng, nó sẽ lâu hơn một chút, nhưng ý tưởng tương tự.

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
Không phải createTempFile thực sự ghi một tệp thực, mà bạn có thể thấy trong hệ thống tệp?
nhà phát triển android

bạn đúng về mặt kỹ thuật. sử dụng đoạn mã trên, tệp tạm thời sẽ tồn tại cho đến khi chương trình thoát hoặc nó bị chương trình xóa.
cobbzilla

Tài liệu của deleteOnExit nói rằng bạn không nên dựa vào nó để làm việc (và tôi nghĩ rằng nó thực sự không làm được gì cả): developer.android.com/reference/java/io/… . Ngoài ra, nếu bạn biết cách phát trực tuyến âm thanh mà không cần bất kỳ tệp nào, vui lòng viết về nó tại đây: stackoverflow.com/q/36552381/878126
android developer

4
Nói chung, tôi muốn ứng dụng xóa tệp tạm thời khi làm như vậy là hợp lý. Tôi sử dụng deleteOnExitnhư một cách kiểm tra sự tỉnh táo bổ sung, không bao giờ dựa vào nó một cách vô điều kiện. Tôi biết rằng trong một số tình huống nhất định ( kill -9ví dụ như JVM), các móc tắt thực hiện việc xóa sẽ không bao giờ được gọi.
cobbzilla

Nếu bạn đang sử dụng tính năng này trên Android, hãy thêm implementation 'org.apache.directory.studio:org.apache.commons.io:2.4'vào gradle.
LordParsley

30

Bạn không thể. Luồng đầu vào chỉ là một luồng dữ liệu chung và không có gì đảm bảo rằng nó thực sự bắt nguồn từ một Tệp. Nếu ai đó đã tạo một InputStream từ việc đọc một dịch vụ web hoặc chỉ chuyển đổi một Chuỗi thành một InputStream, sẽ không có cách nào để liên kết nó với một tệp. Vì vậy, điều duy nhất bạn có thể làm là thực sự ghi dữ liệu từ luồng vào một tệp tạm thời (ví dụ: sử dụng phương thức File.createTempFile) và cấp tệp này vào phương thức của bạn.


7
Thật vậy, File#createTempFile()đây thực sự là đặt cược tốt nhất của bạn.
BalusC

7
Cũng xem File#deleteOnExit(), nguyên nhân khiến JVM cố gắng xóa tệp tự động khi JVM thoát. Tất nhiên, tốt nhất là xóa tệp tạm thời theo cách thủ công và ngay lập tức, khi bạn biết tệp không còn cần thiết và không còn được sử dụng nữa. Nhưng trong một thế giới không hoàn hảo đôi khi những giải pháp không hoàn hảo là cần thiết.
Mike Clark
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.