将.tar.gz文件复制到文件夹

时间:2012-06-11 13:51:52

标签: java vfs truezip

我想将.tar.gz文件的内容复制到2个文件夹,它有大约20个文件,总解压缩大小将> 20 GB。
          我使用了Truezip。

 TFile archive = new TFile(absoluteZipName); // archive with .tar.gz
    TFile[] archFiles = archive.listFiles(); // takes too much time 
    for (TFile t : archFiles) {
         String fileName = t.getName();
          if(fileName.endsWith(".dat"))
              t.cp(new File(destination1+ t.getName()));
          else if(fileName.endsWith(".txt")){
               t.cp(new File(destination2+ t.getName()));
          }
    }
 It takes 3 times above tar xzf command (untar linux) . Have any way to optimize this code for fast copying, memory not an issue.  

    The following code allows fast copying Thanks npe for the good advice.
    (NB: I have no previledge to post the answe now that's why editing question itself)

InputStream is = new FileInputStream(absoluteZipName);
            ArchiveInputStream input = new ArchiveStreamFactory()
               .createArchiveInputStream(ArchiveStreamFactory.TAR, new GZIPInputStream(is));

            ArchiveEntry entry;
            while ((entry = input.getNextEntry()) != null) {
                OutputStream outputFileStream=null;
                if(entry.getName().endsWith(".dat")){
                 File outFile1= new File(destination1, entry.getName());
                     outputFileStream = new FileOutputStream(outFile1); 
                }
                else if(entry.getName().endsWith(".txt")){
                File outFile2= new File(destination2, entry.getName());
                     outputFileStream = new FileOutputStream(outFile2);   
                }
                // use ArchiveEntry#getName() to do the conditional stuff...
                IOUtils.copy(input, outputFileStream,10485760);
            }


    Is threading In file copy will reduce time..? In TZip didn't reduced as they already threading it. anyway I will try tomorrow and will let you Know.

3 个答案:

答案 0 :(得分:1)

似乎listFiles()解压缩了您的gzip文件,以便能够扫描tar文件以获取所有文件名,然后cp(File, File)对其进行扫描再次将流定位在给定文件上。

我要做的是使用Apache Commons Compress并在输入流上执行类似迭代器的扫描,如下所示:

InputStream is = new FileInputStream("/path/to/my/file");
ArchiveInputStream input = new ArchiveStreamFactory()
   .createArchiveInputStream(ArchiveStreamFactory.TAR, new GZIPInputStream(is));

ArchiveEntry entry;
while ((entry = input.getNextEntry()) != null) {

    // use ArchiveEntry#getName() to do the conditional stuff...

}

阅读ArchiveInputStream#getNextEntry()ArchiveEntry的javadoc以获取更多信息。

答案 1 :(得分:0)

您目睹的性能问题的原因是TAR文件格式缺少中央目录。但由于TrueZIP是一个虚拟文件系统,无法预测客户端应用程序的访问模式,因此必须在首次访问时将整个TAR文件解压缩到临时目录。这就是TFile.listFiles()上发生的事情。然后将条目从临时目录复制到目标目录。总而言之,每个入口字节将被读取或写入四次。

要获得最佳性能,您有两种选择:

(a)您可以切换到ZIP文件格式并坚持使用TrueZIP File * API。 ZIP文件有一个中央目录,因此阅读它们不涉及创建临时文件。

(b)您可以将TAR.GZ文件处理为npe所示的流。然后我将它与java.util.zip.GZIPInputStream结合使用,因为该实现基于快速C代码。我还会使用TrueZIP的Streams.copy(InputStream,OuputStream)方法,因为它会使用多线程来实现快速批量复制。

答案 2 :(得分:0)

非常感谢,这是我所做的最后一次,无论如何花费的时间都比tar xzf少。像这样的最终代码片段。

InputStream is = new FileInputStream(absoluteZipName);
ArchiveInputStream input = new ArchiveStreamFactory()
   .createArchiveInputStream(ArchiveStreamFactory.TAR, new GZIPInputStream(is));

ArchiveEntry entry;
while ((entry = input.getNextEntry()) != null) {
    OutputStream outputFileStream=null;
    if(entry.getName().endsWith(".dat")){
     File outFile1= new File(destination1, entry.getName());
         outputFileStream = new FileOutputStream(outFile1); 
    }
    else if(entry.getName().endsWith(".txt")){
    File outFile2= new File(destination2, entry.getName());
         outputFileStream = new FileOutputStream(outFile2);   
    }
    // use ArchiveEntry#getName() to do the conditional stuff...
    IOUtils.copy(input, outputFileStream,10485760);
}

希望我能做更多优化,稍后会做。 非常感谢