【问题标题】:Why does my untar not contain the last bytes为什么我的 untar 不包含最后一个字节
【发布时间】:2012-10-11 10:01:20
【问题描述】:

我编写了一个服务于.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 &lt;= 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 中获取数据?

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

【问题讨论】:

    标签: java zip gzip tar


    【解决方案1】:

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

    【讨论】:

    • 如果我得到的数据数组是块大小的倍数(在本例中为 512),并且最后一位被填充,那将是有意义的。但从表面上看,数组是原始数据的长度(不是块大小的倍数),并且从最后一个完整块到数组末尾都有零。那有意义吗?因此,填充零的数组不会太长。这是正确的长度(数据的预期长度),但错过了最后一个数据(全为零)。
    【解决方案2】:

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

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

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

    我什至不知道 TarOutputStream 上有“closeEntry”之类的东西……我现在知道了! :P

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-18
      • 2018-02-18
      • 1970-01-01
      • 2020-07-05
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      相关资源
      最近更新 更多