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?
It stems from the details of
ImageIOimplementation. You will circumvent the problem if you don’t pass theFileinstance toImageIO.write, but first try to open aFileOutputStreamyourself and pass that towrite.This is a more precise analysis of what happens in
ImageIO.write. Line 1530:Line 1538:
And if you take a look at the implementation of
createImageOutputStream, you’ll see several code paths that returnnull.