Make tar file by Java

前端 未结 4 863
迷失自我
迷失自我 2020-12-03 04:49

I want to use Java to compress a folder to a tar file (in programmatic way). I think there must be an open source or library to do it. However, I cannot find such method.

相关标签:
4条回答
  • 2020-12-03 05:31

    I would look at Apache Commons Compress.

    There is an example part way down this examples page, which shows off a tar example.

    TarArchiveEntry entry = new TarArchiveEntry(name);
    entry.setSize(size);
    tarOutput.putArchiveEntry(entry);
    tarOutput.write(contentOfEntry);
    tarOutput.closeArchiveEntry();
    
    0 讨论(0)
  • 2020-12-03 05:34

    I have produced following code to solve this problem. This code checks if any of files to be incorporated already exist in tar file and updates that entry. Later if it doesn't exist append to the end of 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();
            }
        }
    

    If you use Gradle use following dependency:

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

    I also tried org.xeustechnologies:jtar:1.1 but performance is way below the one provided by org.apache.commons:commons-compress:1.12

    Notes about performance using different implementations:

    Zipping 10 times using Java 1.8 zip:
    - java.util.zip.ZipEntry;
    - java.util.zip.ZipInputStream;
    - java.util.zip.ZipOutputStream;

    [2016-07-19 19:13:11] Before
    [2016-07-19 19:13:18] After
    7 seconds

    Tar-ing 10 times using jtar:
    - org.xeustechnologies.jtar.TarEntry;
    - org.xeustechnologies.jtar.TarInputStream;
    - org.xeustechnologies.jtar.TarOutputStream;

    [2016-07-19 19:21:23] Before
    [2016-07-19 19:25:18] After
    3m55sec

    shell call to Cygwin /usr/bin/tar - 10 times
    [2016-07-19 19:33:04] Before
    [2016-07-19 19:33:14] After
    14 seconds

    Tar-ing 100(hundred) times using 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] Before
    [2016-07-19 23:04:48] After
    3 seconds

    Tar-ing 1000(thousand) times using org.apache.commons.compress:
    [2016-07-19 23:10:28] Before
    [2016-07-19 23:10:48] After
    20 seconds

    0 讨论(0)
  • 2020-12-03 05:39

    You can use the jtar - Java Tar library.

    Taken from their site:

    JTar is a simple Java Tar library, that provides an easy way to create and read tar files using IO streams. The API is very simple to use and similar to the java.util.zip package.

    An example, also from their 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();
    
    0 讨论(0)
  • 2020-12-03 05:49

    .tar archive files are not compressed. You have to run a file compression on it like gzip and turn it into something like .tar.gz.

    If you just want to just archive a directory, take a look at:

    • http://www.trustice.com/java/tar/
    • http://code.google.com/p/jtar/
    0 讨论(0)
提交回复
热议问题