当jar文件从URL打开为InputStream时,JarEntry.getSize()返回-1

时间:2012-01-18 11:59:53

标签: java jar inputstream

我正在尝试从JarInputStream读取文件,文件大小返回-1。我正在从URL访问Jar文件作为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 个答案:

答案 0 :(得分:4)

这是记录在案的行为。 JavadocgetSize() ...

  

“返回条目数据的未压缩大小,如果不知道则返回-1。”

显然,这是未知压缩数据的实际大小的情况。您的申请只需处理此问题。


<强>后续

您评论了另一个答案:

  

虽然我们有总内容大小,但我认为没有单独的文件大小我们无法读取文件。

如果没有大小,您仍然可以使用ByteArrayOutputStream读取文件并对其进行缓冲,然后调用toByteArray()将缓冲的字节提取为byte[]。事实上,鉴于(根据Tom Hawtin的评论),报告的大小可能不正确,无论如何你可能应该这样做,并且只是将报告的大小视为提示......并且只是将其用作ByteArrayOutputStream的初始容量。

(顺便说一下,你问题中的代码看起来可能是以这种方式工作......从第2行到最后一行判断。问题是代码的其余部分没有使用{{1对象。)

答案 1 :(得分:4)

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);
    }
}

答案 2 :(得分:1)

这可能是因为服务该网址的服务器未提供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);
}