为什么我的untar不包含最后的字节

时间:2012-10-11 10:01:20

标签: java zip gzip tar

我写了一个提供.tar.gz文件的休息资源。它工作正常。我已经尝试过请求它,保存数据,解压缩(使用tar xzvf [filename])并获得正确的数据。

但是,我正在尝试使用java.util.zip.GZIPInputStreamorg.apache.tools.tar.TarInputStream解压缩并解压我在JUnit测试中提供的.tar.gz,以验证它是否自动运行。这是我的单元测试中的代码,删除了一些细节:

    HttpResponse response = <make request code here>
    byte[] receivedBytes = FileHelper.copyInputStreamToByteArray(response.getEntity().getContent(), true);

    GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(receivedBytes));
    TarInputStream tarInputStream = new TarInputStream(gzipInputStream);
    TarEntry tarEntry = tarInputStream.getNextEntry();
    ByteArrayOutputStream byteArrayOutputStream = null;
    System.out.println("Record size: " + tarInputStream.getRecordSize());
    while (tarEntry != null) // It only goes in here once
    {
        byteArrayOutputStream = new ByteArrayOutputStream();
        tarInputStream.copyEntryContents(byteArrayOutputStream);
        tarEntry = tarInputStream.getNextEntry();
    }
    byteArrayOutputStream.flush();
    byteArrayOutputStream.close();
    byte[] archivedBytes = byteArrayOutputStream.toByteArray();
    byte[] actualBytes = <get actual bytes>
    Assert.assertArrayEquals(actualBytes, archivedBytes);

最终断言在字节X = (n * 512) + 1处失败,其中n是最大的自然数,因此n * 512 <= ll是数据的长度。也就是说,我正确地获得了512字节数据的最大可能倍数,但是调试测试我可以看到所有剩余的字节都是零。因此,如果数据总量为1000字节,则archivedBytes中的前512个字节是正确的,但最后488个字节全部为零/未设置,如果总数据为262272字节,则得到第一个262144(512 * 512)字节正确,但剩余的字节都是零。

此外,上面的tarInputStream.getRecordSize()系统打印Record size: 512,所以我认为这是某种方式相关的。但是,由于存档在我下载时有效,我想数据必须在那里,并且只有我缺少的东西。

使用1000字节数据进入tarInputStream.copyEntryContents(byteArrayOutputStream)

int numRead = read(buf, 0, buf.length);

numRead是100,但是查看缓冲区,只有前512个字节非零。也许我不应该使用该方法从TarInputStream

中获取数据

如果有人知道它应该如何运作,我会非常感谢任何建议或帮助。

2 个答案:

答案 0 :(得分:1)

您可以指定创建tar存档时要使用的输出块大小。因此,存档的大小将是块大小的倍数。由于存档大小通常不适合整数个块,因此将零添加到最后一个数据块以使其大小合适。

答案 1 :(得分:0)

事实证明我原来的问题是错的,资源代码中的错误。写入时,我没有关闭TarOutputStream上的条目。我猜这在从服务器手动请求它时没有引起任何问题,可能是因为条目是通过连接或其他东西关闭的,但是当从单元测试请求时工作方式不同......虽然我必须承认这不会使很有意义:P

看下面我写作代码的片段,我错过了第3行。

1: tarOutputStream.putNextEntry(tarEntry);
2: tarOutputStream.write(fileRawBytes);
3: tarOutputStream.closeEntry();
4: tarOutputStream.close();

我甚至不知道TarOutputStream上有“closeEntry”这样的东西......我现在就做! :P