Java: распаковка происходит значительно медленнее, чем архивирование - PullRequest
2 голосов
/ 17 июня 2011

У меня есть код, который заархивирует файл, отправляет его по сети, а затем распаковывает на другом конце. Я все еще тестирую код, а источник и назначение совпадают. Архивирование файла занимает около минуты. Распаковка файла занимает порядка часа. Я думаю, что в моем коде должен быть недостаток, чтобы иметь такую ​​большую разницу. Вот код для распаковки:

public String uncompressLocalZip(String filename,String strUUID,ParentEntry pe,boolean bControlFileProgress) {
        final int BUFFER = 2048;
        BufferedOutputStream out  = null;
        ZipInputStream zis = null;

        try {

            FileInputStream fis = new FileInputStream(Constants.conf.getFileDirectory() + Constants.PATH_SEPARATOR + strUUID + Constants.PATH_SEPARATOR + filename);
            zis = new  ZipInputStream(new BufferedInputStream(fis));
            ZipEntry entry;
            long totallength = 0;
            long size = 0;
            if (pe !=null)
                size = pe.getSize();


            while((entry = zis.getNextEntry()) != null) {
                System.out.println("Extracting: " +entry);
                int count;
                byte data[] = new byte[BUFFER];
                // write the files to the disk

                File fileOutput = new File(Constants.conf.getFileDirectory() + Constants.PATH_SEPARATOR + strUUID + Constants.PATH_SEPARATOR + Constants.conf.getUncompressFolderName() + Constants.PATH_SEPARATOR + entry.getName());
                new File(fileOutput.getParent()).mkdirs();


                BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(fileOutput));

                out = new BufferedOutputStream(fos, BUFFER);
                while ((count = zis.read(data, 0, BUFFER)) != -1) {
                       out.write(data, 0, count);
                       totallength += count;

            }
            out.flush();

        }

     }
     catch(Exception e) {
        e.printStackTrace();
        return("FAILED");
     }
     finally {
        try {if ( out!= null) out.close();} catch (IOException ioe) {}
        try {if ( zis!= null) zis.close();} catch (IOException ioe) {}

     }

    return("SUCCESS");      



}

Вот код для почтового индекса:

public void createLocalZip(String filename,ProcessEntry pe) {
    ZipOutputStream out=null;
    try {

        File fileOutput = new File (filename);
        out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(fileOutput)));
        long totallength=0;
        long size = pe.getParentEntry().getSize();

        String strStartDirectory;
        if (pe.getParentEntry().isDirectory())
            strStartDirectory=pe.getParentEntry().getUrl();
        else
            strStartDirectory=pe.getParentEntry().getFolder();



        for (int i=0;i<pe.getParentEntry().tableModel3.getRowCount();i++) {
            FileEntry fe = pe.getParentEntry().tableModel3.getFileEntry(i);
            File fileInput = new File (fe.getUrl());
            FileInputStream input = new FileInputStream(fileInput);
            BufferedInputStream in = new BufferedInputStream(input);

            String strRelativeDir = fe.getUrl().substring(strStartDirectory.length()+1,fe.getUrl().length());

            ZipEntry entry = new ZipEntry(strRelativeDir);

            out.putNextEntry(entry);


            byte[] bbuf = new byte[2048];
            int length=0;




             while ((in != null) && ((length = in.read(bbuf)) != -1)) {

                    out.write(bbuf,0,length);
                    totallength += length;
                    pe.setProgress((int) (totallength*100/size));

             }

             in.close();


        }






    }
    catch (Exception e) {
        System.out.println(e.getMessage());
    }
    finally {
        try {if (out!=null) out.close();} catch(IOException ioe){}
    }


}

Обновление: степень сжатия для этого конкретного теста составляет около 90% (от 1,2 ГБ до 100 МБ). Таким образом, я полагаю, что это может быть дополнительная запись на диск для разархивирования или архивирования, хотя я ожидаю, что разница будет близка к разнице 10X против 60X.

Ответы [ 3 ]

2 голосов
/ 17 июня 2011

не оборачивайте ваш OutputStream дважды с помощью BufferedOutputStream (вам нужна только 1 оболочка BufferedOutputStream) и не закрывайте его после того, как вы закончите запись в него.

также, ZipEntry s могут быть каталогами, поэтому проверьтеэто и обрабатывать соответственно.

0 голосов
/ 17 июня 2011

Рассмотрите возможность использования специализированной библиотеки для архивирования / разархивирования. http://sevenzipjbind.sourceforge.net/ может помочь.

0 голосов
/ 17 июня 2011

У меня нет действительно большого файла для тестирования вашего кода, поэтому я могу только догадываться.

  1. Вы говорите, что размер вашего несжатого архива превышает 1 ГБ. Это может быть больше, чем умещается в вашей памяти, и если что-то заставляет виртуальную машину помещать все в память, она должна будет поменяться. Наблюдайте за вашей программой с помощью профилировщика.

  2. Убедитесь, что вы закрыли каждый FileOutputStream после записи в него. (Вы создаете их много и закрываете только последний.)

  3. Я не уверен насчет реализации ZipInputStream (возможно, она заставляет ваш BufferedStream буферизовать большую часть данных). Вместо этого вы можете попробовать ZipFile (что, в основном, обеспечивает произвольный доступ).

...