#java #image #stream
#java #изображение #поток
Вопрос:
Я записываю изображения и другие данные в двоичный файл. Когда я считываю изображение через ImageIO.read (InputStream) из этого файла, он считывает изображение, все в порядке, но метод закрывает данный входной поток, и я не могу продолжить чтение других данных.
- Почему так сделано?
- Тогда как читать изображение без закрытия потока?
РЕДАКТИРОВАТЬ: это простой код, который записывает изображение и строку после в файл:
File f = new File("test.bin");
if(f.exists())
f.delete();
f.createNewFile();
DataOutputStream os = new DataOutputStream(new FileOutputStream(f));
BufferedImage img = ImageIO.read(new File("test.jpg"));
ImageIO.write(img, "jpg", os);
os.writeUTF("test string after image");
os.close();
И код, который считывает все:
DataInputStream is = new DataInputStream(new FileInputStream(f));
BufferedImage img = ImageIO.read(is);
String s = is.readUTF(); // on this line EOFException occurs
System.out.println(s);
Вывод NetBeans:
Exception in thread "main" java.io.EOFException
at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:340)
at java.io.DataInputStream.readUTF(DataInputStream.java:589)
at java.io.DataInputStream.readUTF(DataInputStream.java:564)
at mediamanager.Main.test(Main.java:105)
at mediamanager.Main.main(Main.java:44)
Может быть, я делаю что-то не так?
Комментарии:
1. Где я был, когда увидел исключение EOFException? Он просто читает все байты до конца, он не закрывает входной поток!
Ответ №1:
Цитата из документации ImageIO.read(InputStream)
Этот метод не закрывает предоставленный входной поток после завершения операции чтения; при желании вызывающий объект обязан закрыть поток.
Акцент не мой.
Проблема в другом. Возможно, в вашем коде.
Комментарии:
1. Да, я прочитал это. Но в моем коде чтение следующих байтов возвращает -1 и дальнейшее исключение EOFException. Я пытаюсь сделать простой код и опубликовать здесь, если я воспроизведу эту ошибку.
2. Очень странно. Я провел небольшой эксперимент, и кажется, что метод ImageIO.read() считывает больше байтов, чем строго необходимо для чтения изображения. Например, если я запишу 10 000 байт после изображения, я смогу прочитать только 7998 байт после чтения изображения. Я понятия не имею, как это исправить, кроме как зная размер (N) каждого изображения, прочитав N байтов в массиве байтов и прочитав изображение из этого массива байтов.
3. И также кажется, что у вас могла быть обратная ошибка: bugs.java.com/view_bug.do?bug_id=6687964
4. Итак, это ошибка… Что ж, остается записать длину изображения и прочитать его в отдельный поток. Спасибо за вашу помощь!
Ответ №2:
Я вижу две возможные причины такого поведения:
- Программа чтения изображений использует буфер для чтения данных из потока для повышения производительности. Таким образом, он считывает больше данных из потока.
- Также программа чтения изображений может попытаться прочитать EXIF для уже проанализированного изображения. Такая информация обычно добавляется в конце файла, чтобы избежать полной перезаписи файла, когда вы просто добавляете пару фрагментов информации об изображении.
Попробуйте ImageIO.setUseCash(false)
, это может помочь.
Комментарии:
1. Я предлагаю лучшее решение для этого хранилища.
2. Прежде всего, вы должны определить размер данных изображения перед его записью. [Размер] [Изображение] [Текст]. Чтобы прочитать точное количество байтов из потока, вы должны использовать свое собственное расширение InputStream (я не нашел ни одного применимого в java.io ). Что-то вроде следующего: ` private int sizeLeft; @Override int read() { if (sizeLeft < 0) return -1; int readed = origin.read(); if (readed != -1) sizeLeft—; return прочитано; } ` и так далее. Сделайте то же самое для доступных и rest ‘read’ методов.
3. Я попытался записать больше данных после записи строки и вывода позиции во входном потоке. Да, reader считывает поток до конца, но я изменил формат на PNG, который не имеет EXIF.