Проблема с tar при сжатии Apache Commons - PullRequest
1 голос
/ 14 января 2010

Я с трудом пытаюсь скопировать некоторые файлы, используя библиотеку сжатия.

Мой код следующий и взят из примеров вики на commons.compress:

    private static File createTarFile(String[] filePaths, String saveAs) throws Exception{

    File tarFile = new File(saveAs);
    OutputStream out = new FileOutputStream(tarFile);

    TarArchiveOutputStream aos = (TarArchiveOutputStream) new ArchiveStreamFactory().createArchiveOutputStream("tar", out);

    for(String filePath : filePaths){
        File file = new File(filePath);
        TarArchiveEntry entry = new TarArchiveEntry(file);
        entry.setSize(file.length());
        aos.putArchiveEntry(entry);
        IOUtils.copy(new FileInputStream(file), aos);
        aos.closeArchiveEntry();
    }
    aos.finish();
    out.close();


    return tarFile;
}

В процессе нет ошибки, но когда я пытаюсь распаковать файл, я получаю следующее:

XXXX:XXXX /home/XXXX$ tar -xf typeCommandes.tar
tar: Unexpected EOF in archive
tar: Unexpected EOF in archive
tar: Error is not recoverable: exiting now

Кроме того, архив немного меньше по размеру, чем исходный файл, что ненормально для tar, поэтому есть проблема ...

-rw-r--r--  1 XXXX nobody 12902400 Jan 14 17:11 typeCommandes.tar
-rw-r--r--  1 XXXX nobody 12901888 Jan 14 17:16 typeCommandes.csv

Кто-нибудь может сказать мне, что я делаю не так? Спасибо

Ответы [ 4 ]

3 голосов
/ 14 января 2010

Вы не закрываете TarArchiveOutputStream. Добавить aos.close() после aos.finish()

2 голосов
/ 25 мая 2010

Небольшая поправка к коду выше. Он не закрывает входной поток, в то время как Apache lib предполагает, что поток управляется путем вызова клиента. Смотрите исправление ниже (поместите этот код после строки 'aos.putArchiveEntry (entry)'):

FileInputStream fis = new FileInputStream(fileForPuttingIntoTar);
IOUtils.copy(fis, aos);
fis.close();
aos.closeArchiveEntry();
0 голосов
/ 20 июля 2016

Смотрите также мой ответ здесь

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();
        }
    }
0 голосов
/ 14 января 2010

пример здесь -> http://commons.apache.org/compress/examples.html использует метод putNextEntry (entry) , который, как вам кажется, опущен.

...