Скопировать файлы.tar.gz в папку
Я хочу скопировать содержимое файлов.tar.gz в папку 2, в ней около 20 файлов, а общий размер разархивированного файла будет>20 ГБ.
Я использовал 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 ответа
Спасибо 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);
}
Надеюсь, я смогу сделать еще несколько оптимизаций, сделаю позже. большое спасибо
Кажется, что 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
для получения дополнительной информации.
Причиной проблемы с производительностью, с которой вы столкнулись, является то, что в формате файла TAR отсутствует центральный каталог. Но поскольку TrueZIP является виртуальной файловой системой и не может предсказать шаблон доступа клиентского приложения, при первом доступе он должен разархивировать весь файл TAR во временный каталог. Это то, что происходит в TFile.listFiles(). Затем вы копируете записи из временного каталога в целевые каталоги. Таким образом, в целом каждый входной байт будет прочитан или записан четыре раза.
Чтобы добиться максимальной производительности, у вас есть два варианта:
(а) Вы можете переключиться на формат файла ZIP и придерживаться API-интерфейса TrueZIP File *. ZIP-файлы имеют центральный каталог, поэтому их чтение не требует создания временных файлов.
(б) Вы можете обработать файл TAR.GZ как поток, как показано в npe. Затем я бы объединил это с java.util.zip.GZIPInputStream, потому что эта реализация основана на быстром C-коде. Я бы также использовал метод TrueZIP Streams.copy(InputStream, OuputStream), потому что он будет использовать многопоточность для действительно быстрого массового копирования.