0

我想将 .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.
4

3 回答 3

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...

}

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

于 2012-06-11T14:11:08.217 回答
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) 方法,因为它将使用多线程进行真正快速的批量复制。

于 2012-06-12T02:15:26.423 回答
0

谢谢 npe ,这是我完成的最后一个,无论如何它比 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);
}

希望我可以做更多的优化,以后会做。非常感谢

于 2012-06-12T03:38:16.230 回答