【问题标题】:File from InputStream来自 InputStream 的文件
【发布时间】:2014-04-11 20:13:39
【问题描述】:

是的,这个问题已经被问了几百万次了,我相信我已经全部看过了。它们非常“有时”、很慢,或者不是我需要的。

在一个项目中,我使用以下代码使用从 GET 接收的 InputStream 将其转换为 PDF。这在我的物理设备和模拟器(Genymotion 2.1.1,Emulator API 18 4.3)上每次都能完美运行。请注意,有些东西被编辑掉了,而且 PDF 通常很小,小于 1 MB。

public abstract class MyPDFFile extends File implements ApiModel{

public MyPDFFile(InputStream inputStream){
    super(context.getExternalFilesDir(
            Environment.DIRECTORY_DOWNLOADS), "my_pdf.pdf");

    if (externalStorageIsWritable()) {
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            FileOutputStream fileInputStream = new FileOutputStream(this);
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileInputStream));

            int readLine;
            char[] cbuf = new char[1];

            do {
                readLine = bufferedReader.read(cbuf);
                bufferedWriter.write(cbuf);
            } while (readLine != -1);
            bufferedWriter.close();
        }
        catch(IOException e){
            // Didn't work
        }
    }
    else{
        // Cant write
    }
} 

我想到了这个新项目,我可以使用相同的代码从互联网下载一个 APK 到设备。不,绝对不是这样。我最终尝试了 Inputstream to File:

FileOutputStream fileOutputStream = new FileOutputStream(file);

byte[] buffer = new byte[1];
while ( (read(buffer)) > 0 ) {

    fileOutputStream.write(buffer);
}
fileOutputStream.close();
close();

这适用于我的模拟器,并且工作正常。我开始在我的设备上进行测试......不是那么多,这很奇怪,因为工作的 PDF 代码可以在我的模拟器和设备上运行。我尝试将缓冲区的大小调整为 512 的各种倍数(这导致文件非常小,比如几 KB,到非常大,大约是 apk 大小的两倍,大约 5.6 MB)。

另外,还有一件奇怪的事情:我永远无法让它在构造函数之外成功保存。当我在那里进行保存时,InputStream 很好,我的文件被创建,yadayada,当我使用成功的代码时,我只是在之后重命名文件,因为我在构造函数中可以访问的是 InputStream。如果我决定“不,当我有合适的东西时我想给它命名”并简单地将 InputStream 保存到我的对象中,它永远不会正常工作。下载的文件永远不能超过 4KB。我试过extends InputStreamextends BufferedInputStream 无济于事。

如果需要,我可以发布更多代码。我只能访问来自我的 GET 请求的 InputStream;我正在使用 browep Android HTTP 库,这就是我能得到的所有东西,而无需尝试弄乱库本身(或覆盖其中的方法)。

【问题讨论】:

  • 为什么new byte[1];中有1个?
  • 你为什么要扩展File
  • 我在这里使用了来自 S/O 的答案。没有其他原因。不过,我尝试了多种大小的数组,但都没有奏效(实际上它们让情况变得更糟)。我正在扩展文件,因此我不必在其中包含实际的“文件”对象。
  • 另外,你为什么使用这个库?我似乎不是很普遍。 (另外,还有一个我经常使用的 1 行文件下载:stackoverflow.com/questions/576513/…
  • 好的。我只是问,因为它不是很常用,它可能有很多没人知道的缺陷。 android 团队几个月前发布了一个名为Volley 的库,它很好地处理了json。

标签: java android rest inputstream download


【解决方案1】:

问题是您正在逐字节读取文件。这可能需要大量时间。相反,以更大的块读取文件,例如 4 或 8 KB:

int file_chunk_size = 1024 * 4; //4KBs, written like this to easily change it to 8
byte[] buffer = new byte[file_chunk_size];
int bytesRead = 0;
while ( (bytesRead = read(buffer)) > 0 ) {
    fileOutputStream.write(buffer, 0, bytesRead);
}

【讨论】:

  • 这对于花费太长时间的情况是有意义的,但这不起作用(在我的场景中)。我尝试了 4kb 和 8kb。我会说使用 4kb 缓冲区确实给了我一个稍大的文件,但总共只有大约 8kb。只是为了确保有人说,我将在这段代码之后直接关闭我的 fileOutputStream 和 Inputstream。
  • 一般?正在下载一个 5.6MB 的文件,但仅以以下两种方式结束:总共 1-8kb,正确的大小和文件,但仅在模拟器中,或大于实际大小,这意味着文件中有额外的信息,它会崩溃。你的建议?第一个问题:它最终还是太小了。
  • @kentarosu 那么问题似乎出在作为参数传递给MyPDFFile 类的流上。而是做这个扩展File 类的奇怪设计,将逻辑移动到您从服务接收真正的InputStream 的方法中,并使用我在此处提供的代码从那里下载文件。在方法之间传递InputStream 时,我遇到了类似的问题。
猜你喜欢
  • 1970-01-01
  • 2011-01-30
  • 2012-06-20
  • 2011-10-19
  • 2013-02-28
  • 2012-01-07
  • 2017-01-28
  • 1970-01-01
  • 2012-04-08
相关资源
最近更新 更多