问题
Here is my code flow for which file content is getting lost and I think may be IOUtils.toByteArray() line is problem, please guide what is actually going wrong here.
File content getting lost :
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();
Now length value here is 0 basically no content. Let me tell you that inputStream received from downloadApi() has content for sure thats given. But if I try below modification in code then I'm getting length of file.
File content NOT getting lost:
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();
Now here I'm getting file content. Can some body tell what is technically wrong here in first code snippet ?
TIA
回答1:
No it doesn't.
The first version of your code (reproduced below with some added commentary) fails because you are reading from a stream that is already at the end of stream position.
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();
When you try to copy from a stream that is at the end of stream, you get ... zero bytes. And that means you get an empty output file.
回答2:
No, this stream should be closed.
This is target method of 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);
来源:https://stackoverflow.com/questions/53281591/does-ioutils-tobytearrayinputstream-method-internally-close-inputstream-object