【问题标题】:Add an entry to a tar file without overwriting its existing contents向 tar 文件添加条目而不覆盖其现有内容
【发布时间】:2012-04-04 07:34:40
【问题描述】:

我需要将配置文件添加到现有的 tar 文件中。我正在使用 apache.commons.compress 库。以下代码 sn -p 正确添加了条目,但会覆盖 tar 文件的现有条目。

public static void injectFileToTar () throws IOException, ArchiveException {
        String agentSourceFilePath = "C:\\Work\\tar.gz\\";
        String fileToBeAdded = "activeSensor.cfg";
        String unzippedFileName = "sample.tar";

    File f2 = new File(agentSourceFilePath+unzippedFileName); // Refers to the .tar file
    File f3 = new File(agentSourceFilePath+fileToBeAdded);    // The new entry to be added to the .tar file

    // Injecting an entry in the tar
    OutputStream tarOut = new FileOutputStream(f2);
    TarArchiveOutputStream aos = (TarArchiveOutputStream) new  ArchiveStreamFactory().createArchiveOutputStream("tar", tarOut);
    TarArchiveEntry entry = new TarArchiveEntry(fileToBeAdded);
    entry.setMode(0100000);
    entry.setSize(f3.length());
    aos.putArchiveEntry(entry);
    FileInputStream fis = new FileInputStream(f3);
    IOUtils.copy(fis, aos);
    fis.close();
    aos.closeArchiveEntry();
    aos.finish();
    aos.close();
    tarOut.close(); 

}

在检查 tar 时,仅找到“activeSensor.cfg”文件,并且发现 tar 的初始内容缺失。 “模式”是否设置不正确?

【问题讨论】:

    标签: java


    【解决方案1】:

    问题是TarArchiveOutputStream 不会自动读取现有存档,这是您需要做的事情。大致如下:

    CompressorStreamFactory csf = new CompressorStreamFactory();
    ArchiveStreamFactory asf = new ArchiveStreamFactory();
    
    String tarFilename = "test.tgz";
    String toAddFilename = "activeSensor.cfg";
    File toAddFile = new File(toAddFilename);
    File tempFile = File.createTempFile("updateTar", "tgz");
    File tarFile = new File(tarFilename);
    
    FileInputStream fis = new FileInputStream(tarFile);
    CompressorInputStream cis = csf.createCompressorInputStream(CompressorStreamFactory.GZIP, fis);
    ArchiveInputStream ais = asf.createArchiveInputStream(ArchiveStreamFactory.TAR, cis);
    
    FileOutputStream fos = new FileOutputStream(tempFile);
    CompressorOutputStream cos = csf.createCompressorOutputStream(CompressorStreamFactory.GZIP, fos);
    ArchiveOutputStream aos = asf.createArchiveOutputStream(ArchiveStreamFactory.TAR, cos);
    
    // copy the existing entries    
    ArchiveEntry nextEntry;
    while ((nextEntry = ais.getNextEntry()) != null) {
        aos.putArchiveEntry(nextEntry);
        IOUtils.copy(ais, aos, (int)nextEntry.getSize());
        aos.closeArchiveEntry();
    }
    
    // create the new entry
    TarArchiveEntry entry = new TarArchiveEntry(toAddFilename);
    entry.setSize(toAddFile.length());
    aos.putArchiveEntry(entry);
    IOUtils.copy(new FileInputStream(toAddFile), aos, (int)toAddFile.length());
    aos.closeArchiveEntry();
    
    aos.finish();
    
    ais.close();
    aos.close();
    
    // copies the new file over the old
    tarFile.delete();
    tempFile.renameTo(tarFile);
    

    几点说明:

    • 此代码不包含任何异常处理(请添加适当的try-catch-finally 块)
    • 此代码不处理大小超过 2147483647 (Integer.MAX_VALUE) 的文件,因为它仅将文件大小读取为整数精度字节(请参阅强制转换为 int)。但是,这不是问题,因为 Apache Compress 无论如何都不能处理超过 2 GB 的文件。

    【讨论】:

    • 谢谢,它成功了。我不得不稍微调整代码,因为我无法直接以 .tar.gz 文件格式执行您共享的整个代码。所以我必须先解压缩文件才能得到 .tar 格式。按照建议的方式在 tar 文件中注入所需的条目后,我不得不再次重新压缩它。对于解压缩和重新压缩,我使用了 java.util.zip.GZIPInputStream 和 java.util.zip.GZIPOutputStream 实用程序。
    【解决方案2】:

    尝试改变

    OutputStream tarOut = new FileOutputStream(f2);

    OutputStream tarOut = new FileOutputStream(f2, true); //设置追加为真

    【讨论】:

    • 谢谢。我做了上面的改变。 tar 内容被保留,但新条目 (activeSensor.cfg) 不会添加到 tar。我是否将路径或传递给 TarArchiveEntry 构造函数的参数弄乱了?
    • 在我去这里搜索之前,我正在使用这种方法。似乎这会导致条目超出 tar 存档的末尾,所以我会收到一个错误,但我的新文件不会在那里。
    猜你喜欢
    • 1970-01-01
    • 2021-09-18
    • 2011-02-18
    • 2012-03-31
    • 1970-01-01
    • 1970-01-01
    • 2019-07-23
    • 2015-04-29
    • 2022-01-22
    相关资源
    最近更新 更多