Java Struts DiskFile.getInputStream()在文件大小更改时返回ByteArrayInputStream和FileArrayInputStream

Java Struts DiskFile.getInputStream()在文件大小更改时返回ByteArrayInputStream和FileArrayInputStream,java,java-8,struts-1,fileinputstream,bytearrayinputstream,Java,Java 8,Struts 1,Fileinputstream,Bytearrayinputstream,我试图分析应用程序中最近发现的一个问题,并意识到我的inputStream.reset()方法失败,因为我试图操作FileInputStream 似乎我对apache的DiskFile.getInputStram()的方法调用根据特定的文件大小阈值返回ByteArrayInputStream实例(标记支持)或FileInputStream(标记不支持)实例 我必须获取此inputstream的代码是: FormFile file = multipartForm.getFiles().get(0)

我试图分析应用程序中最近发现的一个问题,并意识到我的
inputStream.reset()
方法失败,因为我试图操作
FileInputStream

似乎我对apache的
DiskFile.getInputStram()
的方法调用根据特定的文件大小阈值返回
ByteArrayInputStream
实例(标记支持)或
FileInputStream
(标记不支持)实例

我必须获取此inputstream的代码是:

FormFile file = multipartForm.getFiles().get(0); // It's always one file
InputStream is = file.getInputStream();

// Read the stream and did job
// Now I want to reset it.
// bad coding from my side because I didn't check markSupported

is.reset();

// Got IO error immediately after this. But anything below 256KB is ok

我相信这在Oracle JDK文档或apache站点的某个地方提到/解释过。但似乎记不起任何参考资料。有人知道这种行为是否合理吗

我不熟悉Struts API,但对我来说,如果返回类型是
InputStream
,而不是特定的子类,那么您就无法保证返回流的实际类型

由于调用
reset()
仅在具有前面的
标记(readlimit)
调用时有效,因此一般直接处理未指定的
InputStream
类型:

InputStream inputStream = …
int readlimit = …

if(!inputStream.markSupported()) {
    inputStream = new BufferedInputStream(inputStream, readlimit);
}

inputStream.mark(readlimit);
// read some date, not more than readlimit
inputStream.reset();

我不熟悉Struts API,但对我来说,当返回类型是
InputStream
而不是特定的子类时,似乎无法保证返回流的实际类型

由于调用
reset()
仅在具有前面的
标记(readlimit)
调用时有效,因此一般直接处理未指定的
InputStream
类型:

InputStream inputStream = …
int readlimit = …

if(!inputStream.markSupported()) {
    inputStream = new BufferedInputStream(inputStream, readlimit);
}

inputStream.mark(readlimit);
// read some date, not more than readlimit
inputStream.reset();

因此,
DiskFile.getInputStram()
返回一个
InputStream
,其底层实现是
ByteArrayInputStream
FileInputStream
,具体取决于文件的大小?是-如果我的测试正确,那么Windows上大于256KB的任何内容都将返回FileInputStream实现,但是较低的大小将是ByteArrayInputStream。你能检查一下来源吗?例如,我在这里查看,但情况并非如此好吧,让我们假设这是真的-为什么在调用
reset
之前不能执行
instanceOf
检查?我的意思是,他们返回一个
InputStream
——这意味着他们可以在任何时间和任何版本更改返回类型…@Eugene:也许,
FormFile
实际上是一个委托给…所以
DiskFile.getInputStram()
返回一个
InputStream
,它的底层实现是
ByteArrayInputStream
FileInputStream
,具体取决于文件的大小?是-如果我的测试正确,那么Windows上大于256KB的任何内容都将返回FileInputStream实现,但是较低的大小将是ByteArrayInputStream。你能检查一下来源吗?例如,我在这里查看,但情况并非如此好吧,让我们假设这是真的-为什么在调用
reset
之前不能执行
instanceOf
检查?我的意思是他们返回一个
InputStream
-这意味着他们可以在任何时间和任何版本更改返回类型…@Eugene:也许,
FormFile
实际上是一个委托给…的文件,我不确定BufferedInputStream是否始终工作。我见过一些实例,其中IOException由于重置发生在无效标记上而被抛出。如果内容字节可用,只使用ByteArrayInputStream会更安全。那是你的错。您读取的字节数不得超过指定的
readLimit
字节数,否则标记无效且不再支持
reset()
。使用
ByteArrayInputStream
可以避免错误行为,因为它不检查
readLimit
,但在调用
reset()
之前读取的字节数超过指定的字节数仍然是无效用法。当然,您可以先将所有内容读入
byte[]
数组,但为什么还要费心于
mark()
reset()
?如果代码仅适用于现有数组,则不需要处理
InputStream
。只需使用数组。@ha9u63ar:它的支持方式是:“如果自创建流以来未调用方法标记,或者自上次调用标记以来从流中读取的字节数大于上次调用时要标记的参数,则可能会引发IOException。”引发不是强制性的。虽然我希望
ByteArrayInputStream
也能抛出,但为了避免只对
ByteArrayInputStream
起作用的代码似乎是个xy问题。为什么需要标记/重置?当您想要强制使用
ByteArrayInputStream
时,必须首先将所有字节读入数组,这意味着要知道大小。然而,一旦你有了这个数组,你就已经用
InputStream
做了所有你能做的事情,
标记
/
重置
提供的一切,就是再次做同样的事情,再次将数据读入数组,如果你已经有一个包含所有数据的数组,这是没有意义的。即使你真的需要拷贝,你也可以拷贝数组…当你想做的只是将流重置到开头时,你可以再次调用
file.getInputStream()
,然后你有一个输入流,它将从零位再次读取…我不确定BufferedInputStream是否总能工作。我见过一些实例,其中IOException由于重置发生在无效标记上而被抛出。如果内容字节可用,只使用ByteArrayInputStream会更安全。那是你的错。您读取的字节数不得超过指定的
readLimit
字节数,否则标记无效且不再支持
reset()
。使用
ByteArrayInputStream
可以避免错误行为,它不检查
readLimit
,而是读取mo