JarEntry.getSize () возвращает -1, когда файлы JAR открываются как InputStream из URL - PullRequest
6 голосов
/ 18 января 2012

Я пытаюсь прочитать файл из JarInputStream, и размер файла возвращает -1.Я получаю доступ к файлу JAR с URL-адреса как inputStream.

        URLConnection con = url.openConnection();

        JarInputStream jis = new JarInputStream(con.getInputStream());
        JarEntry je = null;

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

Ответы [ 3 ]

4 голосов
/ 24 июня 2012
byte[] classbytes = null;
JarInputStream jis = new JarInputStream(is);
JarEntry je = null;
String jename = null;
while((je = jis.getNextJarEntry()) != null){
    jename = je.getName();
    if(je.getSize() != -1){
        classbytes = new byte[(int)je.getSize()];
        int len = (int) je.getSize();
        int offset = 0;
        while (offset != len)
            offset += jis.read(classbytes, offset, len - offset);
        classes.put(jename, classbytes);
    } else {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        while(true){
            int qwe = jis.read();
            if(qwe == -1) break;
            baos.write(qwe);
        }
        classbytes = baos.toByteArray();
        classes.put(jename, classbytes);
    }
}
4 голосов
/ 18 января 2012

Это документированное поведение. Javadoc говорит, что getSize() ...

"Возвращает несжатый размер входных данных или -1, если неизвестно."

Очевидно, что это ситуация, когда фактический размер несжатых данных не известен.Ваша заявка будет только иметь дело с этим.


FOLLOWUP

Вы прокомментировали другой ответ:

Хотя мы имеемобщий размер контента, я думаю, без индивидуального размера файла мы не можем прочитать файлы.

Если у вас нет размера, вы все равно можете прочитать файл и поместить его в буфер, используя ByteArrayOutputStream, затем вызовите toByteArray(), чтобы извлечь буферизованные байты как byte[].На самом деле, учитывая, что (согласно комментарию Тома Хоутина) сообщенный размер может быть неправильным, вы, возможно, должны все равно сделать это, и просто воспринимать сообщаемый размер как подсказку ... и просто использовать его как *Начальная емкость 1030 *.

(Кстати, код в вашем вопросе выглядит так, как будто он должен был работать именно так ... судя по 2-ой и последней строке. Проблема в том, что остальныекод не использует объект baos.)

1 голос
/ 18 января 2012

Это может быть связано с тем, что сервер, обслуживающий этот URL, не предоставляет contentLenght. это похоже на то, когда вы иногда загружаете файл с помощью браузера и он говорит 33Kb / ?? загружено (в отличие от загруженного 33Kb / 2049Kb).

Чтобы быстро проверить, так ли это, вы можете сделать что-то вроде этого:

URL url = new URL(yourUrl);
conn = url.openConnection();
size = conn.getContentLength();
if(size < 0) {
    System.out.println("Could not determine file size.");
} else {
    System.out.println(yourUrl + "\nSize: " + size);
}
...