5

I read How do I append files to a tar archive in java?, append files to an archive without reading/rewriting the whole archive and Add an entry to a tar file without overwriting its existing contents but no good answer was given. Moreover I do not have enough reputation to post comments. So I created a new question here.

Is there a way to append a file in a tar archive? I would like to replace a file if it exists already.

I have started to write the following method but when the file is added, it erases the archive content. I didn't find any example on the apache compress website.

    static final Logger LOG = Logger.getLogger(ShellClient.class);

public void appendFileInTarArchive(String tarPath, String tarFileName, String file2WriteName, String file2WriteContent) throws IOException {
    if (tarPath == null || tarFileName == null || tarFileName.isEmpty()) {
        LOG.warn("The path or the name of the tar archive is null or empty.");
        return;
    }
    final File tarFile = new File(tarPath, tarFileName);
    final File fileToAdd = new File(tarPath, file2WriteName);
    FileUtils.write(fileToAdd, file2WriteContent);

    if (file2WriteName == null || file2WriteName.isEmpty()) {
        LOG.warn("The name of the file to append in the archive is null or empty.");
        return;
    }

    TarArchiveOutputStream aos = null;
    OutputStream out = null;

    try {
        out = new FileOutputStream(tarFile);

        aos = (TarArchiveOutputStream) new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.TAR, out);

        // create a new entry
        final TarArchiveEntry entry = new TarArchiveEntry(fileToAdd);
        entry.setSize(fileToAdd.length());

        // add the entry to the archive
        aos.putArchiveEntry(entry);
        InputStream is = new FileInputStream(fileToAdd);
        final int byteCopied = IOUtils.copy(is, aos);
        if (LOG.isDebugEnabled()) {
            LOG.debug(byteCopied+" bytes inserted in the tar archive from "+fileToAdd);
        }
        is.close();
        aos.closeArchiveEntry();
        aos.finish();
        aos.flush();
        aos.close();
        out.flush();
        out.close();

    } catch (ArchiveException e) {
        LOG.error(e.getMessage(), e);
    } catch (IOException e) {
        LOG.error(e.getMessage(), e);
    } finally {
        IOUtils.closeQuietly(aos);
        IOUtils.closeQuietly(out);
        FileUtils.deleteQuietly(fileToAdd);
    }
}
Community
  • 1
  • 1
Maxbester
  • 2,207
  • 7
  • 37
  • 64

1 Answers1

5

Finally I succeeded to do it using this post.

I created a copy of the tar archive and copied to entire content to it. Then I delete the old tar archive.

public void appendFileInTarArchive(String tarPath, String tarFileName, String file2WriteName, String file2WriteContent) throws AuthenticationException, IOException {
    if (tarPath == null || tarFileName == null || tarFileName.isEmpty()) {
        LOG.warn("The path or the name of the tar archive is null or empty.");
        return;
    }
    final File tarFile = new File(tarPath, tarFileName);
    final File fileToAdd = new File(tarPath, file2WriteName);
    FileUtils.write(fileToAdd, file2WriteContent);

    if (file2WriteName == null || file2WriteName.isEmpty()) {
        LOG.warn("The name of the file to append in the archive is null or empty.");
        return;
    }

    ArchiveStreamFactory asf = new ArchiveStreamFactory();

    File tempFile = new File(tarPath, "tmpTar.tar");
    tempFile.createNewFile();

    try {
        FileInputStream fis = new FileInputStream(tarFile);
        ArchiveInputStream ais = asf.createArchiveInputStream(ArchiveStreamFactory.TAR, fis);

        FileOutputStream fos = new FileOutputStream(tempFile);
        ArchiveOutputStream aos = asf.createArchiveOutputStream(ArchiveStreamFactory.TAR, fos);

        // copy the existing entries    
        ArchiveEntry nextEntry;
        while ((nextEntry = ais.getNextEntry()) != null) {
            aos.putArchiveEntry(nextEntry);
            IOUtils.copy(ais, aos);
            aos.closeArchiveEntry();
        }

        // create the new entry
        TarArchiveEntry entry = new TarArchiveEntry(file2WriteName);
        entry.setSize(fileToAdd.length());
        aos.putArchiveEntry(entry);
        IOUtils.copy(new FileInputStream(fileToAdd), aos);
        aos.closeArchiveEntry();

        aos.finish();

        ais.close();
        aos.close();

        // copies the new file over the old
        tarFile.delete();
        tempFile.renameTo(tarFile);

    } catch (ArchiveException e) {
        LOG.error(e.getMessage(), e);
    } catch (IOException e) {
        LOG.error(e.getMessage(), e);
    } finally {
        FileUtils.deleteQuietly(fileToAdd);
    }
}
Community
  • 1
  • 1
Maxbester
  • 2,207
  • 7
  • 37
  • 64