java javax.imageio.ImageIO 创建 ImageInputStream 的问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6929230/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
javax.imageio.ImageIO Problem creating ImageInputStream
提问by Marquinio
I have a Servlet in Tomcat 5.5 that reads local images sitting on a folder. The image is then sent back to an Applet.
我在 Tomcat 5.5 中有一个 Servlet,它读取位于文件夹中的本地图像。然后将图像发送回 Applet。
I'm getting this "javax.imageio.IIOException: Can't create an ImageInputStream!" error and not sure whats causing it.
我收到这个“javax.imageio.IIOException:无法创建 ImageInputStream!” 错误,不确定是什么原因造成的。
Has anyone had this problem before? Could this be a Thread issue in the ImageIO? I can't reproduce this issue since it occurs about 3 times for every 1000 requests.
以前有人遇到过这个问题吗?这可能是 ImageIO 中的线程问题吗?我无法重现这个问题,因为它每 1000 个请求发生大约 3 次。
EDIT: This is the Servlet code that reads the image. I just use the ImageIO.read(File) in its static form inside the Servlet's doPost method the same way below:
编辑:这是读取图像的 Servlet 代码。我只是在 Servlet 的 doPost 方法中以静态形式使用 ImageIO.read(File) ,方法如下:
doPost(req,resp){
...
BufferedImage image = ImageIO.read(imageFile);
...
}
Here is the source code for javax.imageio.ImageIO.read(File):
这是 javax.imageio.ImageIO.read(File) 的源代码:
public static BufferedImage read(File input) throws IOException {
if (input == null) {
throw new IllegalArgumentException("input == null!");
}
if (!input.canRead()) {
throw new IIOException("Can't read input file!");
}
ImageInputStream stream = createImageInputStream(input);
if (stream == null) {
throw new IIOException("Can't create an ImageInputStream!");
}
BufferedImage bi = read(stream);
if (bi == null) {
stream.close();
}
return bi;
}
采纳答案by Thomas
The source I have (Java5 but I doubt it has changed a lot) states that if there are no ImageInputStream service providers registered, the createImageInputStream
method returns null and thus you get that exception.
我拥有的来源(Java5 但我怀疑它已经改变了很多)指出,如果没有注册 ImageInputStream 服务提供者,则该createImageInputStream
方法返回 null,因此您会收到该异常。
From the JavaDoc on IIORegistry.getDefaultInstance()
which is used by ImageIO
:
根据JavaDoc上IIORegistry.getDefaultInstance()
所使用的ImageIO
:
Each ThreadGroup will receive its own instance; this allows different Applets in the same browser (for example) to each have their own registry.
每个 ThreadGroup 都会收到自己的实例;这允许同一浏览器中的不同小程序(例如)每个都有自己的注册表。
Thus it might actually be a threading problem in that you get a plain new instance of IIORegistry
.
因此,它实际上可能是一个线程问题,因为您获得了一个普通的IIORegistry
.
Edit: digging deeper into the source I found the following:
编辑:深入挖掘源我发现以下内容:
Most likely you'd get a FileImageInputStream
, since you pass in a file. However, if an exception occurs the service provider returns null
. Thus there might be a FileNotFoundException
or any other IOException
being thrown which causes the stream not to be created.
很可能你会得到一个FileImageInputStream
,因为你传入了一个文件。但是,如果发生异常,服务提供者将返回null
。因此,可能会抛出aFileNotFoundException
或任何其他IOException
导致流无法创建的抛出。
Unfortunately, there's no logging in the code, thus you'd have to debug somehow. It's probably due to missing file permissions, a corrupted/incomplete file or the file missing.
不幸的是,代码中没有日志记录,因此您必须以某种方式进行调试。这可能是由于缺少文件权限、文件损坏/不完整或文件丢失。
Here's the Java5 source for FileImageInputStreamSpi#createInputStreamInstance()
这是 Java5 源代码 FileImageInputStreamSpi#createInputStreamInstance()
public ImageInputStream createInputStreamInstance(Object input,
boolean useCache,
File cacheDir) {
if (input instanceof File) {
try {
return new FileImageInputStream((File)input);
} catch (Exception e) {
return null;
}
} else {
throw new IllegalArgumentException();
}
}
回答by BalusC
If the sole functional requirement is to read images from local disk and return it unmodifiedto the HTTP response using a servlet, then you do notneed the ImageIO
at all. It only adds unnecessary overhead and other problems like you're having now.
如果唯一的功能要求是读取本地磁盘映像,并将其返回未修改使用servlet的HTTP响应,那么你就不会需要ImageIO
在所有。它只会增加不必要的开销和您现在遇到的其他问题。
Get rid of the ImageIO
stuff and just stream the raw image straight from disk to HTTP response, along a set of proper response headers. For example,
摆脱这些ImageIO
东西,只需将原始图像从磁盘直接流式传输到 HTTP 响应,以及一组适当的响应标头。例如,
String name = request.getParameter("name");
File file = new File("/path/to/images", name);
response.setContentType(getServletContext().getMimeType(file.getName()));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
InputStream input = null;
OutputStream output = null;
try {
input = new BufferedInputStream(new FileInputStream(file));
output = new BufferedOutputStream(response.getOutputStream());
byte[] buffer = new byte[8192];
for (int length; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
} finally {
if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
}
That's all. You only need ImageIO
whenever you would like to manipulate the image in server's memory before returning it, e.g. resizing, transforming or something.
就这样。您只需要ImageIO
在您想在返回之前操作服务器内存中的图像时才需要,例如调整大小、转换或其他东西。
Another, more robust, example of such a servlet can be found hereand a more advanced one here.
回答by Yoichi
Where is your use of close() methods within the exception handling? Streams have to be closed when there are exceptions, too, as well as normal termination of the block of the code.
您在异常处理中在哪里使用 close() 方法?当出现异常以及代码块的正常终止时,流也必须关闭。
The symptom sounds like you run out of heap space or sometime.
症状听起来像是你用完了堆空间或某个时候。
It is not the coding errors that others pointed out, since the problem is intermittent.
这不是其他人指出的编码错误,因为问题是间歇性的。