2009-07-22 11 views
2

Я знаю, я знаю, кто захочет сжать или распаковать большие файлы в java. Совершенно необоснованно. На данный момент приостановить недоверие и предположим, что у меня есть веская причина для разжатия большого файла ZIP.Случайный доступ к сжатому файлу без использования ZipFile (поскольку ZipFile имеет основную ошибку)

выпуск 1: ZipFile имеет bug (bug # 6280693), солнце исправлено это в java 1.6 (Mustang). Исправление не является полезным, поскольку наше программное обеспечение должно поддерживать java 1.4. Ошибка, как я понимаю, работает так. Когда выполняется следующий код, Java выделяет кусок памяти, достаточно большой для хранения всего файла.

ZipFile zipFile = new ZipFile("/tmp/myFile.zip"); 

Если /tmp/myFile.zip - 4gb, java выделяет 4gb. Это вызывает исключение из кучи. К сожалению, размер кучи + 4 ГБ не является приемлемым решением. = (

Решение выпустить 1:. Используйте ZipInputStream, чтобы иметь дело с файлом в виде потока и, таким образом, уменьшить и контролировать объем памяти

byte[] buf = new byte[1024]; 
FileInputStream fs = new FileInputStream("/tmp/myFile.zip") 
ZipInputStream zipIn = new ZipInputStream(fs); 

ZipEntry ze = zipIn.getNextEntry(); 

while (ze != null){ 
    while ((int cr = zipIn.read(buf, 0, 1024)) > -1) 
    System.out.write(buf, 0, len); 
    ze = zipIn.getNextEntry(); 
} 

Выпуск 2: Я хотел бы получить доступ к ZipEntries случайно, что. ., я хотел бы только распаковывать один ZipEntry, без необходимости искать через весь поток в настоящее время я строй список из zipEntries, называется ZES:

 ZipInputStream zin = new ZipInputStream("/tmp/myFile.zip"); 

     ZipEntry ze = zin.getNextEntry(); 
     List<ZipEntry> zes = new ArrayList<ZipEntry>(); 

     while(ze!=null){ 
      zes.add(ze); 
      ze = zin.getNextEntry(); 
     } 

Тогда, когда мне нужно распаковывать конкретный ZipEntry I итерации через все zi pEntries, пока не найду соответствующий zipEntry, который я затем распакую.

 ZipEntry ze = in.getNextEntry(); 
     while (! ze.getName().equals(queryZe.getName())){ 
      ze = zin.getNextEntry(); 
     } 

     int cr; 

     while ((cr = zin.read(buf)) > -1) 
      System.out.write(buf, 0, cr); 

Quertion: ZipFile имеет возможность случайного доступа к ZipEntries.

new BufferedInputStream(zipFile.getInputStream(zipEntry)); 

Как я могу получить эту же способность без использования ZipFile?

Обратите внимание, что у ZipInputStream есть несколько довольно strangebehavior.

Особенно хорошая документация по Java и ZipFiles можно найти здесь:

http://commons.apache.org/compress/zip.html

Заметки о переключении замены солнца ZipFile с Apache Commons ZipFile как предложено в ответах:

  1. Солнца ZipFile.entries() всегда возвращает ZipEntries в том порядке, в котором они происходят в файле, тогда как apache commons ZipFile.getEntries() возвращает записи случайным образом заказ. Это вызвало интересную ошибку, потому что в некотором коде предполагалось, что записи будут «в порядке».

ответ

4

Для этой задачи вы можете посмотреть Apache Commons Compress, Apache Commons VFS, или TrueZip. Все они должны быть совместимы с Java 1.4 и, возможно, поддерживать нужные функции.

+0

Ваш ответ сработал, спасибо! –

2

Вы можете посмотреть Apache Commons Compress, который работает с 1.4+, но я не знаю, подвергает ли он ту же ошибку под капотом или нет.

+2

Это не так ли? Http: //commons.apache.org/compress/apidocs/org/apache/commons/compress/archivers/zip/ZipFile.html – toluju

+0

Тогда что это? http://commons.apache.org/compress/apidocs/org/apache/commons/compress/archivers/zip/ZipFile.html – jsight

+0

О, слово! Виноват! Благодаря! =) –