我想将.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.
答案 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);
}
希望我能做更多优化,稍后会做。 非常感谢