Skip to content

Extracting a tar.gz / tgz Archive

QIE bundles Apache Commons Compress, so scripts can untar gzipped tarballs without adding an external library. Pair GzipCompressorInputStream (decompresses the gzip layer) with TarArchiveInputStream (walks the tar entries), then write each entry to disk.

var GzipIn = Packages.org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
var TarIn  = Packages.org.apache.commons.compress.archivers.tar.TarArchiveInputStream;

var archive = qie.newFile('/in/bundle.tar.gz');
var outDir  = '/out/extracted/';
var BUFFER_SIZE = 4096;

var fis   = new java.io.FileInputStream(archive);
var tarIn = new TarIn(new GzipIn(fis));
try {
    var entry;
    while ((entry = tarIn.getNextTarEntry()) !== null) {
        var outPath = outDir + entry.getName();
        if (entry.isDirectory()) {
            new java.io.File(outPath).mkdirs();
            continue;
        }
        var fos  = new java.io.FileOutputStream(outPath, false);
        var dest = new java.io.BufferedOutputStream(fos, BUFFER_SIZE);
        try {
            var buf = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, BUFFER_SIZE);
            var read;
            while ((read = tarIn.read(buf)) !== -1) {
                dest.write(buf, 0, read);
            }
        } finally {
            dest.close();
        }
    }
} finally {
    tarIn.close();
    fis.close();
}

The loop calls getNextTarEntry() once per archive entry; on each iteration the tar stream is positioned at the start of the entry's bytes, ready to be copied out in 4 KB chunks. Directories are created with java.io.File.mkdirs(); files are written as-is via a buffered FileOutputStream.

Caveats

  • outDir + entry.getName() does not normalize paths. If the archive comes from an untrusted source, reject entries whose getName() contains .. to prevent directory-traversal writes.
  • File permissions and timestamps from the tar header (entry.getMode(), entry.getModTime()) are not preserved by this snippet. Add explicit handling if needed.