Java ImageIO: Exception Weirdness
Asked Answered
A

4

5

In my application I was trying to save a BufferedImage to a PNG file using ImageIO. The file is chosen by the user so I need to react to errors that might happend (e.g. user tries to save in a location he has no write permission for). However I am unable to catch the IOException that occurs.

The following code shows the problem. Trying to save to "/foo" should throw an exception for most users on *nix systems, since they do not have write permission in the root directory.

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class IOTest {

    public static void main(String[] args) {
        BufferedImage img = new BufferedImage(640, 480,
                BufferedImage.TYPE_INT_RGB);
        try {
            File f = new File("/foo");
            ImageIO.write(img, "png", f);
        } catch (IOException e) {
            System.out.println("Caught IOException!");
        }
    }
}

However, the exception is not caught. Output:

    java.io.FileNotFoundException: /foo (Permission denied)
    at java.io.RandomAccessFile.open(Native Method)
    at java.io.RandomAccessFile.<init>(RandomAccessFile.java:233)
    at javax.imageio.stream.FileImageOutputStream.<init>(FileImageOutputStream.java:69)
    at com.sun.imageio.spi.FileImageOutputStreamSpi.createOutputStreamInstance(FileImageOutputStreamSpi.java:55)
    at javax.imageio.ImageIO.createImageOutputStream(ImageIO.java:419)
    at javax.imageio.ImageIO.write(ImageIO.java:1530)
    at IOTest.main(IOTest.java:16)
Exception in thread "main" java.lang.NullPointerException
    at javax.imageio.ImageIO.write(ImageIO.java:1538)
    at IOTest.main(IOTest.java:16)

Note that FileNotFoundException is a subclass of IOException so it should get caught. A second catch block did not help either:

catch (FileNotFoundException e) {
    System.out.println("Caught FileNotFoundException!");
} catch (IOException e) {
    System.out.println("Caught IOException!");
}

What am I doing wrong?

Aldebaran answered 22/8, 2012 at 14:1 Comment(0)
T
6

It stems from the details of ImageIO implementation. You will circumvent the problem if you don't pass the File instance to ImageIO.write, but first try to open a FileOutputStream yourself and pass that to write.

This is a more precise analysis of what happens in ImageIO.write. Line 1530:

stream = createImageOutputStream(output);

Line 1538:

stream.close();

And if you take a look at the implementation of createImageOutputStream, you'll see several code paths that return null.

Telfer answered 22/8, 2012 at 14:6 Comment(0)
B
4

It looks like the ImageIO.write method prints the IOException but really doesn't handle it and ends with a NullPointerException. In this specific case of a buggy library, maybe you should catch any RuntimeException...

Of course it will be better to test before if the directory exists and is writable.

Botelho answered 22/8, 2012 at 14:7 Comment(0)
S
0

It seems that ImageIO.write() wraps the FileNotFoundException into a NullPointerException.

You should catch NullPointerException, or better check file existence before invoking ImageIO.write().

Strahan answered 22/8, 2012 at 14:9 Comment(1)
There is no "caused by" to justify your conclusion.Telfer
M
0

By the looks of it the FileNotFoundException is being handled within javax.imageio.ImageIO.write and that failure is causing a null pointer exception. Try to check the file permissions before you try saving it!

Muckraker answered 22/8, 2012 at 14:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.