如何在Java中完全从内存中的对象创建tar或tar.gz归档文件(无文件)

5

如何在Java中创建一个不基于File和实际文件的tar或gzipped tar归档文件?

我发现了commons-compress,但示例和大多数文档都依赖于使用可以由Java File对象引用的已有文件。如果我不想使用File对象,并且想从byte[]构建我的tar归档文件,该怎么办?

TarArchiveEntry的唯一提供设置内容的构造函数接受File,并且没有内容的setter。

来自TarArchiveEntry的文档

TarArchiveEntry(File file)
   Construct an entry for a file.
TarArchiveEntry(File file, String fileName)
    Construct an entry for a file.
1个回答

11
使用commons-compress时,文档中并没有清晰的说明或示例。这里是要点:
//Get the content you want to lay down into a byte[]
byte content[] = "I am some simple content that should be written".getBytes();

//Name your entry with the complete path relative to the base directory
//of your archive. Any directories that don't exist (e.g. "testDir") will 
//be created for you
TarArchiveEntry textFile = new TarArchiveEntry("testDir/hello.txt");

//Make sure to set the size of the entry. If you don't you will not be able
//to write to it
textFile.setSize(content.length);


TarArchiveOutputStream gzOut = null;
try {

    /*In this case I chose to show how to lay down a gzipped archive.
      You could just as easily remove the GZIPOutputStream to lay down a plain tar.
      You also should be able to replace the FileOutputStream with 
      a ByteArrayOutputStream to lay nothing down on disk if you wanted 
      to do something else with your newly created archive
    */
    gzOut = new TarArchiveOutputStream(
                new GZIPOutputStream(
                new BufferedOutputStream(
                new FileOutputStream("/tmp/mytest.tar.gz")
            )));

    //When you put an ArchiveEntry into the archive output stream, 
    //it sets it as the current entry
    gzOut.putArchiveEntry(textFile);

    //The write command allows you to write bytes to the current entry 
    //on the output stream, which was set by the above command.
    //It will not allow you to write any more than the size
    //that you specified when you created the archive entry above
    gzOut.write(content);

    //You must close the current entry when you are done with it. 
    //If you are appending multiple archive entries, you only need  
    //to close the last one. The putArchiveEntry automatically closes
    //the previous "current entry" if there was one
    gzOut.closeArchiveEntry();

} catch (Exception ex) {
    System.err.println("ERROR: " + ex.getMessage());
} finally {
    if (gzOut != null) {
        try {
            gzOut.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

啊,好的。我在StackOverflow上还相对不太有经验。 - anon
@vmarbut 在你的问题中,你指定了内存,但是你提供的答案是将tar保存到"/tmp/mytest.tar.gz"。我知道这是一个旧问题,但是你有没有找到一种不保存文件的方法,因为我在lambda磁盘存储上遇到了512限制的问题。 - Lonergan6275
@Lonergan6275,是的,它在那段代码的注释中。只需使用不同类型的输出流,如ByteArrayOutputStream即可。 - wmarbut
//当你完成当前条目时,必须关闭它。 //如果您正在附加多个存档条目,则只需要关闭最后一个即可。 //putArchiveEntry会自动关闭上一个“当前条目”(如果有的话) gzOut.closeArchiveEntry(); 这是不正确的,您必须每次关闭存档条目,否则将得到一个包含损坏数据的存档。 - Oleg Bezkorovaynyi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接