web-dev-qa-db-fra.com

Créer un fichier tar par Java

Je veux utiliser Java pour compresser un dossier dans un fichier tar (de manière programmatique). Je pense qu'il doit y avoir une source ouverte ou une bibliothèque pour le faire. Cependant, je ne trouve pas une telle méthode.

Sinon, pourrais-je créer un fichier Zip et renommer son nom étendu en .tar?

N'importe qui pourrait suggérer une bibliothèque pour le faire? Merci!

22

Vous pouvez utiliser la jtar - Java Tar .

Tiré de leur site:

JTar est une simple bibliothèque Java Tar, qui fournit un moyen facile de créer et de lire des fichiers tar en utilisant IO streams. L'API est très simple à utiliser et similaire au package Java.util.Zip.

Un exemple, également sur leur site:

   // Output file stream
   FileOutputStream dest = new FileOutputStream( "c:/test/test.tar" );

   // Create a TarOutputStream
   TarOutputStream out = new TarOutputStream( new BufferedOutputStream( dest ) );

   // Files to tar
   File[] filesToTar=new File[2];
   filesToTar[0]=new File("c:/test/myfile1.txt");
   filesToTar[1]=new File("c:/test/myfile2.txt");

   for(File f:filesToTar){
      out.putNextEntry(new TarEntry(f, f.getName()));
      BufferedInputStream Origin = new BufferedInputStream(new FileInputStream( f ));

      int count;
      byte data[] = new byte[2048];
      while((count = Origin.read(data)) != -1) {
         out.write(data, 0, count);
      }

      out.flush();
      Origin.close();
   }

   out.close();
16
Marcelo

Je regarderais Apache Commons Compress .

Il y a un exemple à mi-chemin cette page d'exemples , qui montre un exemple tar.

TarArchiveEntry entry = new TarArchiveEntry(name);
entry.setSize(size);
tarOutput.putArchiveEntry(entry);
tarOutput.write(contentOfEntry);
tarOutput.closeArchiveEntry();
30
nicholas.hauschild

.tar les fichiers d'archive ne sont pas compressés. Vous devez exécuter une compression de fichier dessus comme gzip et le transformer en quelque chose comme .tar.gz.

Si vous voulez simplement archiver un répertoire, jetez un œil à:

8
tskuzzy

J'ai produit le code suivant pour résoudre ce problème. Ce code vérifie si l'un des fichiers à incorporer existe déjà dans le fichier tar et met à jour cette entrée. Plus tard s'il n'existe pas, ajoutez à la fin de l'archive.

import org.Apache.commons.compress.archivers.ArchiveEntry;
import org.Apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.Apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.Apache.commons.compress.archivers.tar.TarArchiveOutputStream;

public class TarUpdater {

        private static final int buffersize = 8048;

        public static void updateFile(File tarFile, File[] flist) throws IOException {
            // get a temp file
            File tempFile = File.createTempFile(tarFile.getName(), null);
            // delete it, otherwise you cannot rename your existing tar to it.
            if (tempFile.exists()) {
                tempFile.delete();
            }

            if (!tarFile.exists()) {
                tarFile.createNewFile();
            }

            boolean renameOk = tarFile.renameTo(tempFile);
            if (!renameOk) {
                throw new RuntimeException(
                        "could not rename the file " + tarFile.getAbsolutePath() + " to " + tempFile.getAbsolutePath());
            }
            byte[] buf = new byte[buffersize];

            TarArchiveInputStream tin = new TarArchiveInputStream(new FileInputStream(tempFile));

            OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(tarFile.toPath()));
            TarArchiveOutputStream tos = new TarArchiveOutputStream(outputStream);
            tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);

            //read  from previous  version of  tar  file
            ArchiveEntry entry = tin.getNextEntry();
            while (entry != null) {//previous  file  have entries
                String name = entry.getName();
                boolean notInFiles = true;
                for (File f : flist) {
                    if (f.getName().equals(name)) {
                        notInFiles = false;
                        break;
                    }
                }
                if (notInFiles) {
                    // Add TAR entry to output stream.
                    if (!entry.isDirectory()) {
                        tos.putArchiveEntry(new TarArchiveEntry(name));
                        // Transfer bytes from the TAR file to the output file
                        int len;
                        while ((len = tin.read(buf)) > 0) {
                            tos.write(buf, 0, len);
                        }
                    }
                }
                entry = tin.getNextEntry();
            }
            // Close the streams
            tin.close();//finished  reading existing entries 
            // Compress new files

            for (int i = 0; i < flist.length; i++) {
                if (flist[i].isDirectory()) {
                    continue;
                }
                InputStream fis = new FileInputStream(flist[i]);
                TarArchiveEntry te = new TarArchiveEntry(flist[i],flist[i].getName());
                //te.setSize(flist[i].length());
                tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
                tos.setBigNumberMode(2);
                tos.putArchiveEntry(te); // Add TAR entry to output stream.

                // Transfer bytes from the file to the TAR file
                int count = 0;
                while ((count = fis.read(buf, 0, buffersize)) != -1) {
                    tos.write(buf, 0, count);
                }
                tos.closeArchiveEntry();
                fis.close();
            }
            // Complete the TAR file
            tos.close();
            tempFile.delete();
        }
    }

Si vous utilisez Gradle, utilisez la dépendance suivante:

compile group: 'org.Apache.commons', name: 'commons-compress', version: '1.+'

J'ai également essayé org.xeustechnologies: jtar: 1.1 mais les performances sont bien inférieures à celles fournies par org.Apache.commons: commons-compress: 1.12

Remarques sur les performances à l'aide de différentes implémentations:

Zipper 10 fois en utilisant Java 1.8 Zip:
- Java.util.Zip.ZipEntry;
- Java.util.Zip.ZipInputStream;
- Java.util.Zip.ZipOutputStream;

[2016-07-19 19:13:11] Avant
[2016-07-19 19:13:18] Après
7 secondes

Tarage 10 fois avec jtar:
- org.xeustechnologies.jtar.TarEntry;
- org.xeustechnologies.jtar.TarInputStream;
- org.xeustechnologies.jtar.TarOutputStream;

[2016-07-19 19:21:23] Avant
[2016-07-19 19:25:18] Après
3 min 55 s

Appel du shell à Cygwin/usr/bin/tar - 10 fois
[2016-07-19 19:33:04] Avant
[2016-07-19 19:33:14] Après
14 secondes

Tarage 100 (cent) fois en utilisant org.Apache.commons.compress:
- org.Apache.commons.compress.archivers.ArchiveEntry;
- org.Apache.commons.compress.archivers.tar.TarArchiveEntry;
- org.Apache.commons.compress.archivers.tar.TarArchiveInputStream;
- org.Apache.commons.compress.archivers.tar.TarArchiveOutputStream;

[2016-07-19 23:04:45] Avant
[2016-07-19 23:04:48] Après
3 secondes

Tarage 1000 (milliers) fois en utilisant org.Apache.commons.compress:
[2016-07-19 23:10:28] Avant
[2016-07-19 23:10:48] Après
20 secondes

4
aprodan