简体   繁体   中英

NullPointerException using ImageIO.read

I'm getting an NPE while trying to read in an image file, and I can't for the life of me figure out why. Here is my line:

BufferedImage source = ImageIO.read(new File(imgPath));

imgPath is basically guaranteed to be valid and right before it gets here it copies the file from the server. When it hits that line, I get this stack trace:

Exception in thread "Thread-26" java.lang.NullPointerException
    at com.ctreber.aclib.image.ico.ICOReader.getICOEntry(ICOReader.java:120)
    at com.ctreber.aclib.image.ico.ICOReader.read(ICOReader.java:89)
    at javax.imageio.ImageIO.read(ImageIO.java:1400)
    at javax.imageio.ImageIO.read(ImageIO.java:1286)
    at PrintServer.resizeImage(PrintServer.java:981)    <---My function
    <Stack of rest of my application here>

Also, this is thrown into my output window:

Can't create ICOFile: Can't read bytes: 2

I have no idea what is going on, especially since the File constructor is succeeding. I can't seem to find anybody who has had a similar problem. Anybody have any ideas? (Java 5 if that makes any difference)

I poked around some more and found that you can specify which ImageReader ImageIO will use and read it in that way. I poked around our codebase and found that we already had a function in place for doing EXACTLY what I was trying to accomplish here. Just for anybody else who runs into a similar issue, here is the crux of the code (some of the crap is defined above, but this should help anybody who tries to do it):

File imageFile = new File(filename);
Iterator<ImageReader> imageReaders = ImageIO.getImageReadersByFormatName("jpeg");
if ( imageReaders.hasNext() ) {
    imageReader = (ImageReader)imageReaders.next();
    stream = ImageIO.createImageInputStream(imageFile);
    imageReader.setInput(stream, true);
    ImageReadParam param = imageReader.getDefaultReadParam();
    curImage = imageReader.read(0, param);
}

Thanks for the suggestions and help all.

Also note that ImageIO.read is not thread-safe (it reuses cached ImageReader s which are not thread-safe).

This means you can't easily read multiple files in parallel. To do that, you'll have to deal with ImageReader s yourself.

The File constructor will almost certainly succeed, regardless of whether it points to a valid/existing file . At the very least, I'd check whether your underlying file exists via the exists() method.

您是否认为文件可能只是损坏了,或者ImageIO试图将其读取为错误的文件类型?

Googling for the ICOReader class results in one hit: IconsFactory from jide-common .
Apparently they had the same problem:

// Using ImageIO approach results in exception like this.
//    Exception in thread "main" java.lang.NullPointerException
//            at com.ctreber.aclib.image.ico.ICOReader.getICOEntry(ICOReader.java:120)
//            at com.ctreber.aclib.image.ico.ICOReader.read(ICOReader.java:89)
//            at javax.imageio.ImageIO.read(ImageIO.java:1400)
//            at javax.imageio.ImageIO.read(ImageIO.java:1322)
//            at com.jidesoft.icons.IconsFactory.b(Unknown Source)
//            at com.jidesoft.icons.IconsFactory.a(Unknown Source)
//            at com.jidesoft.icons.IconsFactory.getImageIcon(Unknown Source)
//            at com.jidesoft.plaf.vsnet.VsnetMetalUtils.initComponentDefaults(Unknown Source)

//    private static ImageIcon createImageIconWithException(final Class<?> baseClass, final String file) throws IOException {
//        try {
//            InputStream resource =
//                    baseClass.getResourceAsStream(file);
//            if (resource == null) {
//                throw new IOException("File " + file + " not found");
//            }
//            BufferedInputStream in =
//                    new BufferedInputStream(resource);
//            return new ImageIcon(ImageIO.read(in));
//        }
//        catch (IOException ioe) {
//            throw ioe;
//        }
//    }

What did they do instead?

private static ImageIcon createImageIconWithException(
        final Class<?> baseClass, final String file)
        throws IOException {
    InputStream resource = baseClass.getResourceAsStream(file);

    final byte[][] buffer = new byte[1][];
    try {
        if (resource == null) {
            throw new IOException("File " + file + " not found");
        }
        BufferedInputStream in = new BufferedInputStream(resource);
        ByteArrayOutputStream out = new ByteArrayOutputStream(1024);

        buffer[0] = new byte[1024];
        int n;
        while ((n = in.read(buffer[0])) > 0) {

            out.write(buffer[0], 0, n);
        }
        in.close();
        out.flush();
        buffer[0] = out.toByteArray();
    } catch (IOException ioe) {
        throw ioe;
    }

    if (buffer[0] == null) {
        throw new IOException(baseClass.getName() + "/" + file
                + " not found.");
    }
    if (buffer[0].length == 0) {
        throw new IOException("Warning: " + file
                + " is zero-length");
    }

    return new ImageIcon(Toolkit.getDefaultToolkit().createImage(
            buffer[0]));
}

So you might want to try the same approach: read the raw bytes and use Toolkit to create an image from them.

"it's a jpeg but doesn't have a jpeg extension."

That might be it.

It appears that the library AC.lib-ICO is throwing the NPE. Since this library is intended to read the Microsoft ICO file format, a JPEG might be a problem for it.

Consider explicitly providing the format using an alternative method .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM