2016-02-16 7 views
1

Я хочу прочитать изображения (.png файлов) в моем проекте, и я хочу, чтобы это работало в файле runnable .jar. Так что я написал этот маленький кусочек кода:Java ImageIO.read() возвращающий нуль

try { 
    InputStream in; 
    in = Loader.class.getClassLoader().getResourceAsStream("buttons.png"); 

    System.out.println(in.read() + ", Reader: " + in);   

    BufferedImage img = ImageIO.read(in); 

    System.out.println(img.getHeight()); 

    in.close(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

Когда я бегу, я получаю следующий результат:

137, Reader: [email protected] 
Exception in thread "main" java.lang.NullPointerException 
    at test.Loader.load(Loader.java:21) 
    at test.MainTest.main(MainTest.java:6) 

МОЯ MainTest делает ничего, но работает этот код, так что я не буду включать его Вот.

Я уже тестировал, если InputStreamnull, как вы, возможно, заметили. Поскольку это, очевидно, не путь к моему файлу, должен быть прав. Мой вопрос: Почему ImageIO.read() возвращается null?

+0

Проверьте, что 'buttons.png' находится в корневом каталоге пути класса Loader. Учитывать регистр. Проверьте файл .jar с помощью 7zip, WinZip и т.п. –

+1

getResource (AsStream) возвращает null, когда ресурс не найден – MadProgrammer

ответ

3

Проблемы с кодом является линией, которая считывает из in перед передачей его ImageIO.read(..) (вы читаете первые байты):

System.out.println(in.read() + ", Reader: " + in); 

Когда вы читаете байты из потока, этот байт эффективно «потребляется» и больше не будет считаться, поэтому ImageIO никогда не увидит этот байт, в результате чего формат файла (PNG) не будет распознан. В этом случае ImageIO.read(..) вернет null.

Просто удалите эту строку, и ваш код должен работать нормально.

Файл представляется присутствующим как in не является null. И значение 137, которое вы печатаете, на самом деле является первым байтом PNG signature, то есть файл прекрасно и правильно включен в ваш JAR.


Если вам действительно нужно заглянуть в байты в потоке перед переходом к ImageIO, вы могли бы сделать что-то вроде:

in.mark(256); // allows you to read up to 256 bytes before calling reset() 
System.out.println(in.read() + ", Reader: " + in); // or whatever you like to do 
in.reset(); // "rewind" to beginning of stream (previous mark) 

Просто будьте осторожны, так как не все потоки поддерживает mark()/reset() методы (вы может протестировать, используя метод boolean markSupported()).

+0

Youre абсолютно прав. Я тоже работал над этим: D. Но большое спасибо за вашу помощь и подробное объяснение :) – Deadbyrd12

1

Как вы уже читали на InputStream перед вызовом ImageIO.read, может случиться так, что функция не может правильно декодировать изображение. Удалите вызов in.read() и проверьте результаты вызовов.