【问题标题】:Does IOUtils.toByteArray(inputStream) method internally close inputStream object?IOUtils.toByteArray(inputStream) 方法是否在内部关闭 inputStream 对象?
【发布时间】:2018-11-13 13:01:38
【问题描述】:

这是我的文件内容丢失的代码流,我认为可能是 IOUtils.toByteArray() 行有问题,请指导此处实际出了什么问题。

文件内容丢失:

InputStream stream = someClient.downloadApi(fileId);
byte[] bytes = IOUtils.toByteArray(stream); 
String mimeType = CommonUtils.fileTypeFromByteArray(bytes);
String fileExtension=FormatToExtensionMapping.getByFormat(mimeType).getExtension();
String filePath = configuration.getDownloadFolder() + "/" ;
String fileName = UUID.randomUUID() + fileExtension;    
File file = new File(filePath+fileName);    
file.createNewFile();    
FileUtils.copyInputStreamToFile(stream,file);    
int length = (int)file.length();

现在这里的长度值是0基本上没有内容。让我告诉你,从 downloadApi() 收到的 inputStream 肯定有内容。但是,如果我尝试在代码中进行以下修改,那么我将获得文件长度。

文件内容不会丢失:

InputStream stream = someClient.downloadApi(fileId);
byte[] bytes = IOUtils.toByteArray(stream);
String mimeType = CommonUtils.fileTypeFromByteArray(bytes);
String fileExtension=FormatToExtensionMapping.getByFormat(mimeType).getExtension();
String filePath = configuration.getDownloadFolder() + "/" ;
String fileName = UUID.randomUUID() + fileExtension;
stream = new ByteArrayInputStream(bytes); //Again converted bytes to stream    
File file = new File(filePath+fileName);    
file.createNewFile();    
FileUtils.copyInputStreamToFile(stream,file);    
int length = (int)file.length();

现在我正在获取文件内容。有人能说出第一个代码 sn-p 在技术上的问题吗?

TIA

【问题讨论】:

  • 我将首先:转储toByteArray() 的结果。你的第二个例子看起来很奇怪,它实际上不应该做任何事情。您不能“重置”流...不要选择“文件长度”,请检查写入磁盘的 内容
  • 另外,ByteArrayInputStream 真的将InputStream 作为输入吗?
  • @GhostCat 是的,我检查了下载的文件,它的第一个 sn-p 有 no content,但有第二个 sn-p 的内容。长度只是说明它没有内容的例子。
  • @CS_noob 谢谢!相应地更新了代码。

标签: java inputstream bytearrayinputstream ioutils


【解决方案1】:

没有。

您的代码的第一个版本(在下面复制并添加了一些注释)失败,因为您正在从已经位于流末尾位置的流中读取。

InputStream stream = someClient.downloadApi(fileId);

// This reads the entire stream to the end of stream.
byte[] bytes = IOUtils.toByteArray(stream);

String mimeType = CommonUtils.fileTypeFromByteArray(bytes);
String fileExtension = 
        FormatToExtensionMapping.getByFormat(mimeType).getExtension();
String filePath = configuration.getDownloadFolder() + "/" ;
String fileName = UUID.randomUUID() + fileExtension;    
File file = new File(filePath+fileName);    
file.createNewFile();    

// Now you attempt to read more data from the stream.
FileUtils.copyInputStreamToFile(stream,file);    

int length = (int)file.length();

当您尝试从位于流末尾的流中复制时,您会得到……零字节。这意味着您会得到一个空的输出文件。

【讨论】:

  • 太棒了!谢谢,这真的解释了为什么我首先得到零字节。此外,它告诉我们如果我们使用IOUtils.toByteArray(stream);,那么在该流对象之后不应用于对流对象进行任何类型的修改,因为它已移至 EOF,除了stream.close()
【解决方案2】:

不,应该关闭此信息流。

这是IOUtils的目标方法:

public static long copyLarge(final InputStream input, final OutputStream output, final byte[] buffer)
        throws IOException {
    long count = 0;
    int n;
    while (EOF != (n = input.read(buffer))) {
        output.write(buffer, 0, n);
        count += n;
    }
    return count;
}

// create stream and use it
InputStream stream = someClient.downloadApi(fileId);
byte[] bytes = IOUtils.toByteArray(stream); 

// then us it again
FileUtils.copyInputStreamToFile(stream,file);

// FIXED VERSION
FileUtils.copyInputStreamToFile(new ByteArrayInputStream(bytes),file);

【讨论】:

  • 感谢您的快速回复!而且我完全理解应该在此处关闭流,但以上两个代码行为怪异,请查看一次,并可以解释那里出了什么问题,为什么内容丢失会很棒。
  • 是的,您的 // FIXED VERSION 代码是我在第二个 sn-p 中所做的。谢谢!
猜你喜欢
  • 2012-03-23
  • 1970-01-01
  • 2019-01-20
  • 1970-01-01
  • 2013-07-03
  • 1970-01-01
  • 2013-10-18
  • 2013-10-15
  • 2012-01-11
相关资源
最近更新 更多