извлечение содержимого записей ZipFile при чтении из byte[] (Java)

У меня есть zip-файл, содержимое которого представлено в виде byte[] но объект исходного файла недоступен. Я хочу прочитать содержимое каждой из записей. Я могу создать ZipInputStream из ByteArrayInputStream байтов и могу прочитать записи и их имена. Однако я не вижу простого способа извлечь содержимое каждой записи.

(Я просмотрел Apache Commons, но и там не вижу простого пути).

ОБНОВЛЕНИЕ Код @Rich решил проблему, спасибо

ЗАПРОС, почему оба примера имеют множитель * 4 (128/512 и 1024*4)?


person peter.murray.rust    schedule 07.10.2009    source источник


Ответы (3)


Если вы хотите обрабатывать вложенные записи zip из потока, см. этот ответ для идей. Поскольку внутренние записи перечислены последовательно, их можно обрабатывать, получая размер каждой записи и считывая это количество байтов из потока.

Обновлено примером, который копирует каждую запись в стандартный вывод:

ZipInputStream is;//obtained earlier

ZipEntry entry = is.getNextEntry();

while(entry != null) {
    copyStream(is, out, entry);

    entry = is.getNextEntry();
}
...

private static void copyStream(InputStream in, OutputStream out,
        ZipEntry entry) throws IOException {
    byte[] buffer = new byte[1024 * 4];
    long count = 0;
    int n = 0;
    long size = entry.getSize();
    while (-1 != (n = in.read(buffer)) && count < size) {
        out.write(buffer, 0, n);
        count += n;
    }
}
person Rich Seller    schedule 07.10.2009
comment
@Богатый. Я указал, что zip-файл недоступен. У меня нет вложенных почтовых индексов. - person peter.murray.rust; 07.10.2009
comment
Я обновил свой ответ, чтобы объяснить, как он все еще может помочь. У вас есть один поток, который может считывать размер каждой записи из потока. - person Rich Seller; 07.10.2009
comment
@Rich, спасибо, я разместил пример, пока вы публиковали свой. Я попробую ваш, потому что мой не работает. - person peter.murray.rust; 07.10.2009
comment
Почему размер массива 1024*4? - person Casebash; 13.05.2010

На самом деле он использует ZipInputStream как InputStream (но не закрывает его в конце каждой записи).

person Tom Hawtin - tackline    schedule 07.10.2009

Немного сложно вычислить начало следующего ZipEntry. См. этот пример, включенный в JDK 6,

public static void main(String[] args) {
    try {
        ZipInputStream is = new ZipInputStream(System.in);
        ZipEntry ze;
        byte[] buf = new byte[128];
        int len;

        while ((ze = is.getNextEntry()) != null) {
            System.out.println("----------- " + ze);

            // Determine the number of bytes to skip and skip them.
            int skip = (int)ze.getSize() - 128;
            while (skip > 0) {
                skip -= is.skip(Math.min(skip, 512));
            }

            // Read the remaining bytes and if it's printable, print them.
            out: while ((len = is.read(buf)) >= 0) {
                for (int i=0; i<len; i++) {
                    if ((buf[i]&0xFF) >= 0x80) {
                        System.out.println("**** UNPRINTABLE ****");

                        // This isn't really necessary since getNextEntry()
                        // automatically calls it.
                        is.closeEntry();

                        // Get the next zip entry.
                        break out;
                    }
                }
                System.out.write(buf, 0, len);
            }
        }
        is.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
person ZZ Coder    schedule 07.10.2009