Ну и собственно пример выше, разобранный чуть подробнее:
50 4B 03 04 //сигнатура хедера локального файла, читать как 0x04034b50
14 00 // version needed to extract, зависит от фич, использованных при
// создании архива, в основном различные алгоритмы сжатия
// 0x14 соответствует версия 2.0
00 00 // general purpose bit flag - свалка различных флагов. Некоторые используются
// разными алгоритмами, некоторые не используются вообще, некоторые зарезервированы
08 00 // метод сжатия, в данном случае Deflate
0D 9D и 5E 43 // DOS-время последней модификации файла, см. структуру FILETIME в WinAPI
33 C3 3A 4D // CRC-32 файла
30 04 00 00 // размер сжатого файла, 1072 байт
80 08 00 00 // размер исходного файла, 2176 байт
0C 00 // совершенно верно, длина имени файла
1C 00 // длина дополнительного поля
50 65 72 73 6F 6E 2E 63 6C 61 73 73 // собственно искомое имя файла. Никакого юникода, старый добрый ASCII
Надеюсь это помогло, если остались вопросы - задавайте, я в своё время немало головной боли помел с зип-файлами.
Судя по комментариям выше, вы уже во всём разобрались (кроме порядка байтов). В целом всё верно, нужно пройтись по всем local file header и достать из них имя. В качестве примера посоветовал бы почитать исодники minizip, входящей в состав zlib.
В частности https://github.com/madler/zlib/blob/master/contrib/minizip/miniunz.c#L234 и подробней о парсинге хедера в https://github.com/madler/zlib/blob/master/contrib/minizip/unzip.c#L1136
Это не Java а C, но, учитывая что вещи довольно низкоуровневые, понять можно.