如果我多次调用它,为什么这种方法有时会给我一个错误

时间:2015-05-27 21:01:10

标签: java

我有一个方法可以保存图像并在保存时显示其进度。总体而言,该方法似乎有效,但如果我多次调用它有时会给我一个IllegalArgumentException错误。

这是堆栈跟踪:

java.lang.IllegalArgumentException: input == null!
    at javax.imageio.ImageIO.getImageReaders(ImageIO.java:641)
    at com.forseth11.ColorEncoder.Encoder.saveImage(Encoder.java:308)
    at com.forseth11.ColorEncoder.Encoder.encode(Encoder.java:82)
    at com.forseth11.ColorEncoder.Encoder$3.run(Encoder.java:376)
    at java.lang.Thread.run(Thread.java:745)

我不知道为什么会出现此错误或如何解决此问题。我需要能够多次调用此方法来连续保存多个图像。

以下是方法:

private void saveImage(final BufferedImage image, final String string, final File outputfile) throws IOException, InterruptedException {
        Thread thread = new Thread(new Runnable(){

            public void run() {
                try {
                    ImageIO.write(image, string, outputfile);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        });
        thread.start();

        try {
            ImageInputStream iis = ImageIO.createImageInputStream(outputfile);
            Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
            if (readers.hasNext()) {
                ImageReader reader = readers.next();
                reader.setInput(iis);
                try {
                    BufferedImage img = reader.read(0);

                    ByteArrayOutputStream baos = new ByteArrayOutputStream();//This is the line the error is pointing to.
                    try {
                        ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
                        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("png");
                        if (writers.hasNext()) {
                            ImageWriter writer = writers.next();
                            writer.addIIOWriteProgressListener(new IIOWriteProgressListener() {
                                public void imageStarted(ImageWriter source, int imageIndex) {
                                }

                                public void imageProgress(ImageWriter source, float percentageDone) {
                                    System.out.println("UPDATE: " + percentageDone);//TODO
                                }

                                public void imageComplete(ImageWriter source) {
                                }

                                public void thumbnailStarted(ImageWriter source, int imageIndex, int thumbnailIndex) {
                                }

                                public void thumbnailProgress(ImageWriter source, float percentageDone) {
                                }

                                public void thumbnailComplete(ImageWriter source) {
                                }

                                public void writeAborted(ImageWriter source) {
                                }
                            });

                            writer.setOutput(ios);
                            try {
                                writer.write(img);
                            } finally {
                                writer.removeAllIIOWriteProgressListeners();
                            }
                        }
                    } finally {
                        reader.removeAllIIOReadProgressListeners();
                    }
                } finally {
                    reader.removeAllIIOReadProgressListeners();
                }
            }
        } catch (IOException exp) {
            exp.printStackTrace();
        }

        thread.join();//I added this so it will not leave the method until the image is saved.
    }

我获得了从here获取图像保存百分比的代码。我修改了一下。

如何使用此方法保存图像并打印保存的百分比而不会出现错误?另外,为什么在连续两次调用方法时并不总是给我一个错误?

3 个答案:

答案 0 :(得分:2)

不要使用以下线程

Thread thread = new Thread(new Runnable(){
    public void run() {
        try {
            ImageIO.write(image, string, outputfile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
});
thread.start();

因为当outputfile没有准备就绪时,你继续使用以下代码

ImageInputStream iis = ImageIO.createImageInputStream(outputfile);
Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);

答案 1 :(得分:0)

错误是这些行的结果,每个堆栈跟踪,所以你的:

        ImageInputStream iis = ImageIO.createImageInputStream(outputfile);
        Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);

我用google搜索了ImageIO源代码并在此处找到了它: this issue

抛出异常的源代码片段是:

     public static Iterator<ImageReader> More ...getImageReaders(Object input) {
640         if (input == null) {
641             throw new IllegalArgumentException("input == null!");
642         }
643         Iterator iter;
644         // Ensure category is present
645         try {
646             iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
647                                               new CanDecodeInputFilter(input),
648                                               true);
649         } catch (IllegalArgumentException e) {
650             return Collections.emptyIterator();
651         }
652 
653         return new ImageReaderIterator(iter);
654     }

“ImageIO.createImageInputStream(outputfile)”方法调用中有多种情况可能导致问题,基于查看源:服务提供者对注册表的调用是抛出异常,还是返回的服务提供者迭代器没有成员。在这两种情况下,都会得到null返回。

我建议下载jar代码本地并在此源代码中设置条件断点,以便您可以确切地看到发生了哪种情况。

希望有助于找到问题的根源。

答案 2 :(得分:0)

事实证明我不理解我正在使用的代码。显然,当我只想写自己的时候,它正试图读取文件。

这是我的新方法,似乎可以解决任何人遇到类似问题的方法:

private void saveImage(final BufferedImage image, final String string, final File outputfile) throws IOException, InterruptedException {
        Thread thread = new Thread(new Runnable(){

            public void run() {
                try {
                    ImageIO.write(image, string, outputfile);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        });
        thread.start();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(string);
            if (writers.hasNext()) {
                ImageWriter writer = writers.next();
                writer.addIIOWriteProgressListener(new IIOWriteProgressListener() {
                    public void imageStarted(ImageWriter source, int imageIndex) {
                    }

                    public void imageProgress(ImageWriter source, float percentageDone) {
                        System.out.println("UPDATE: " + percentageDone);//TODO
                    }

                    public void imageComplete(ImageWriter source) {
                    }

                    public void thumbnailStarted(ImageWriter source, int imageIndex, int thumbnailIndex) {
                    }

                    public void thumbnailProgress(ImageWriter source, float percentageDone) {
                    }

                    public void thumbnailComplete(ImageWriter source) {
                    }

                    public void writeAborted(ImageWriter source) {
                    }
                });

                writer.setOutput(ios);
                try {
                    writer.write(image);
                } finally {
                    writer.removeAllIIOWriteProgressListeners();
                }
            }

        thread.join();
    }