File: src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
Issue: Cannot Read Winzip Archives With Unicode Extra Fields
I have a zip file created with WinZip containing Unicode extra fields. Upon attempting to extract it with org.apache.commons.compress.archivers.zip.ZipFile, ZipFile.getInputStream() returns null for ZipArchiveEntries previously retrieved with ZipFile.getEntry() or even ZipFile.getEntries(). See UTF8ZipFilesTest.patch in the attachments for a test case exposing the bug. The original test case stopped short of trying to read the entries, that's why this wasn't flagged up before. 
The problem lies in the fact that inside ZipFile.java entries are stored in a HashMap. However, at one point after populating the HashMap, the unicode extra fields are read, which leads to a change of the ZipArchiveEntry name, and therefore a change of its hash code. Because of this, subsequent gets on the HashMap fail to retrieve the original values.
ZipFile.patch contains an (admittedly simple-minded) fix for this problem by reconstructing the entries HashMap after the Unicode extra fields have been parsed. The purpose of this patch is mainly to show that the problem is indeed what I think, rather than providing a well-designed solution.
The patches have been tested against revision 1210416.

Buggy code:
private void resolveLocalFileHeaderData(Map<ZipArchiveEntry, NameAndComment>
                                        entriesWithoutUTF8Flag)
    throws IOException {
    // changing the name of a ZipArchiveEntry is going to change
    // the hashcode - see COMPRESS-164
    // Map needs to be reconstructed in order to keep central
    // directory order
    for (ZipArchiveEntry ze : entries.keySet()) {
        OffsetEntry offsetEntry = entries.get(ze);
        long offset = offsetEntry.headerOffset;
        archive.seek(offset + LFH_OFFSET_FOR_FILENAME_LENGTH);
        byte[] b = new byte[SHORT];
        archive.readFully(b);
        int fileNameLen = ZipShort.getValue(b);
        archive.readFully(b);
        int extraFieldLen = ZipShort.getValue(b);
        int lenToSkip = fileNameLen;
        while (lenToSkip > 0) {
            int skipped = archive.skipBytes(lenToSkip);
            if (skipped <= 0) {
                throw new RuntimeException("failed to skip file name in"
                                           + " local file header");
            }
            lenToSkip -= skipped;
        }
        byte[] localExtraData = new byte[extraFieldLen];
        archive.readFully(localExtraData);
        ze.setExtra(localExtraData);
        offsetEntry.dataOffset = offset + LFH_OFFSET_FOR_FILENAME_LENGTH
            + SHORT + SHORT + fileNameLen + extraFieldLen;

        if (entriesWithoutUTF8Flag.containsKey(ze)) {
            String orig = ze.getName();
            NameAndComment nc = entriesWithoutUTF8Flag.get(ze);
            ZipUtil.setNameAndCommentFromExtraFields(ze, nc.name,
                                                     nc.comment);
            if (!orig.equals(ze.getName())) {
                nameMap.remove(orig);
                nameMap.put(ze.getName(), ze);
            }
        }
    }
}

Fixed code:
private void resolveLocalFileHeaderData(Map<ZipArchiveEntry, NameAndComment>
                                        entriesWithoutUTF8Flag)
    throws IOException {
    // changing the name of a ZipArchiveEntry is going to change
    // the hashcode - see COMPRESS-164
    // Map needs to be reconstructed in order to keep central
    // directory order
    Map<ZipArchiveEntry, OffsetEntry> origMap =
        new LinkedHashMap<ZipArchiveEntry, OffsetEntry>(entries);
    entries.clear();
    for (ZipArchiveEntry ze : origMap.keySet()) {
        OffsetEntry offsetEntry = origMap.get(ze);
        long offset = offsetEntry.headerOffset;
        archive.seek(offset + LFH_OFFSET_FOR_FILENAME_LENGTH);
        byte[] b = new byte[SHORT];
        archive.readFully(b);
        int fileNameLen = ZipShort.getValue(b);
        archive.readFully(b);
        int extraFieldLen = ZipShort.getValue(b);
        int lenToSkip = fileNameLen;
        while (lenToSkip > 0) {
            int skipped = archive.skipBytes(lenToSkip);
            if (skipped <= 0) {
                throw new RuntimeException("failed to skip file name in"
                                           + " local file header");
            }
            lenToSkip -= skipped;
        }
        byte[] localExtraData = new byte[extraFieldLen];
        archive.readFully(localExtraData);
        ze.setExtra(localExtraData);
        offsetEntry.dataOffset = offset + LFH_OFFSET_FOR_FILENAME_LENGTH
            + SHORT + SHORT + fileNameLen + extraFieldLen;

        if (entriesWithoutUTF8Flag.containsKey(ze)) {
            String orig = ze.getName();
            NameAndComment nc = entriesWithoutUTF8Flag.get(ze);
            ZipUtil.setNameAndCommentFromExtraFields(ze, nc.name,
                                                     nc.comment);
            if (!orig.equals(ze.getName())) {
                nameMap.remove(orig);
                nameMap.put(ze.getName(), ze);
            }
        }
        entries.put(ze, offsetEntry);
    }
}