Несоответствие между размером ZipEntry для ZipInputStream и JarInputStream

У меня есть куча файлов изображений в zip-файле, который я читаю, используя ZipInputStream и перебирая ZipEntry из апплета.

   ZipInputStream zis = new ZipInputStream(in);
        ZipEntry ze = null;
        while ((ze = zis.getNextEntry()) != null) {
            htSizes.put(ze.getName(), new Integer((int) ze.getSize()));
            if (ze.isDirectory()) {
                continue;
            }
            int size = (int) ze.getSize();
            // -1 means unknown size.
            if (size == -1) {
                size = ((Integer) htSizes.get(ze.getName())).intValue();
            }
            byte[] b = new byte[(int) size];
            int rb = 0;
            int chunk = 0;
            while (((int) size - rb) > 0) {
                chunk = zis.read(b, rb, (int) size - rb);
                if (chunk == -1) {
                    break;
                }
                rb += chunk;
            }
            // add to internal resource hashtable
            htJarContents.put(ze.getName(), b);
        }

Однако, когда я помещаю эти изображения в подписанную банку, «ze.getSize()» приходит как -1, и файл изображения читается неправильно.

Может ли кто-нибудь помочь мне в этом отношении.


person Deepak Chaudhry    schedule 23.01.2012    source источник
comment
Вы действительно не должны усекать размер до int. Также см. ответ @JonSkeet ниже.   -  person Perception    schedule 23.01.2012
comment
возможный дубликат JarEntry .getSize() возвращает -1, когда файлы jar открываются как InputStream из URL   -  person Stephen C    schedule 23.01.2012
comment
Почему бы просто не получить входной поток сжатого изображения и не передать его ImageIO.read(InputStream)?   -  person Andrew Thompson    schedule 24.01.2012


Ответы (3)


Да, -1 означает, что размер неизвестен - непонятно, почему вы помещаете его в карту, а затем снова извлекаете.

По сути, если размер неизвестен, вы должны продолжать чтение буферов, пока read не вернет -1. Один простой способ - создать ByteArrayOutputStream и продолжить копирование из ZipEntry в него, а затем, когда вы закончите чтение, просто получите массив байтов из ByteArrayOutputStream. Он будет обрабатывать любое необходимое изменение размера.

person Jon Skeet    schedule 23.01.2012

getSize() возвращает несжатый размер данных записи или -1, если он неизвестен.

Поэтому, если возвращаемый размер отрицательный, добавьте его к 0xffffffffl, чтобы получить правильное значение.

Пример:

long size = ze.getSize();
if (size < 0) {
    size = 0xffffffffl + size ;
}

Ссылка: Отрицательное значение возвращено для ZipEntry.getSize()< /а>

person Areeg Samir    schedule 03.08.2013
comment
Как примечание, OP получает -1 от getSize, а не большое отрицательное число, вызванное переполнением int. Ошибка, упомянутая в вашем посте, также была исправлена ​​​​в обновлении java 6 18. - person David; 02.06.2014

Этот вопрос похож на JarEntry.getSize() возвращает -1, когда файлы jar открываются как InputStream из URL, и ответ тот же.

В javadoc специально указано, что этот метод возвращает -1, если размер не может быть определен. И (по словам Тома Хотина) также возможно, что возвращаемый размер неотрицательный ... и неправильный.

Суть в том, что вам нужно рассматривать сообщаемый размер только как подсказку и считывать весь поток в расширяемый байтовый буфер (например, ByteArrayOutputStream).

person Stephen C    schedule 23.01.2012