예제 #1
0
        /*
         * Returns an input stream on the data of the specified {@code ZipEntry}.
         *
         * @param entry
         *            the ZipEntry.
         * @return an input stream of the data contained in the {@code ZipEntry}.
         * @throws IOException
         *             if an {@code IOException} occurs.
         * @throws IllegalStateException if this ZIP file has been closed.
         */
        public java.io.InputStream getInputStream(ZipEntry entry) // throws IOException {

        /*
         * Make sure this ZipEntry is in this Zip file.  We run it through
         * the name lookup.
         */
        {
            entry = getEntry(entry.getName());
            if (entry == null)
            {
                return(null);
            }

            /*
             * Create a ZipInputStream at the right part of the file.
             */
            java.io.RandomAccessFile raf = mRaf;
            lock (raf) {
                // We don't know the entry data's start position. All we have is the
                // position of the entry's local header. At position 28 we find the
                // length of the extra data. In some cases this length differs from
                // the one coming in the central header.
                RAFStream rafstrm = new RAFStream(raf,
                                                  entry.mLocalHeaderRelOffset + 28);
                int localExtraLenOrWhatever = ler.readShortLE(rafstrm);
                // Skip the name and this "extra" data or whatever it is:
                rafstrm.skip(entry.nameLen + localExtraLenOrWhatever);
                rafstrm.mLength = rafstrm.mOffset + entry.compressedSize;
                if (entry.compressionMethod == ZipEntry.DEFLATED)
                {
                    int bufSize = java.lang.Math.max(1024, (int)java.lang.Math.min(entry.getSize(), 65535L));
                    return(new ZipInflaterInputStream(rafstrm, new Inflater(true), bufSize, entry));
                }
                else
                {
                    return(rafstrm);
                }
            }
        }
예제 #2
0
        /*
         * Find the central directory and read the contents.
         *
         * <p>The central directory can be followed by a variable-length comment
         * field, so we have to scan through it backwards.  The comment is at
         * most 64K, plus we have 18 bytes for the end-of-central-dir stuff
         * itself, plus apparently sometimes people throw random junk on the end
         * just for the fun of it.</p>
         *
         * <p>This is all a little wobbly.  If the wrong value ends up in the EOCD
         * area, we're hosed. This appears to be the way that everybody handles
         * it though, so we're in good company if this fails.</p>
         */
        private void readCentralDir()  //throws IOException {

        /*
         * Scan back, looking for the End Of Central Directory field.  If
         * the archive doesn't have a comment, we'll hit it on the first
         * try.
         *
         * No need to synchronize mRaf here -- we only do this when we
         * first open the Zip file.
         */
        {
            long scanOffset = mRaf.length() - ENDHDR;

            if (scanOffset < 0)
            {
                throw new ZipException("too short to be Zip");
            }

            long stopOffset = scanOffset - 65536;

            if (stopOffset < 0)
            {
                stopOffset = 0;
            }

            while (true)
            {
                mRaf.seek(scanOffset);
                if (ZipEntry.readIntLE(mRaf) == 101010256L)
                {
                    break;
                }

                scanOffset--;
                if (scanOffset < stopOffset)
                {
                    throw new ZipException("EOCD not found; not a Zip archive?");
                }
            }

            /*
             * Found it, read the EOCD.
             *
             * For performance we want to use buffered I/O when reading the
             * file.  We wrap a buffered stream around the random-access file
             * object.  If we just read from the RandomAccessFile we'll be
             * doing a read() system call every time.
             */
            RAFStream rafs = new RAFStream(mRaf, mRaf.getFilePointer());

            java.io.BufferedInputStream bin = new java.io.BufferedInputStream(rafs, ENDHDR);

            int diskNumber         = ler.readShortLE(bin);
            int diskWithCentralDir = ler.readShortLE(bin);
            int numEntries         = ler.readShortLE(bin);
            int totalNumEntries    = ler.readShortLE(bin);

            /*centralDirSize =*/ ler.readIntLE(bin);
            long centralDirOffset = ler.readIntLE(bin);

            /*commentLen =*/ ler.readShortLE(bin);

            if (numEntries != totalNumEntries ||
                diskNumber != 0 ||
                diskWithCentralDir != 0)
            {
                throw new ZipException("spanned archives not supported");
            }

            /*
             * Seek to the first CDE and read all entries.
             * However, when Z_SYNC_FLUSH is used the offset may not point directly
             * to the CDE so skip over until we find it.
             * At most it will be 6 bytes away (one or two bytes for empty block, 4 bytes for
             * empty block signature).
             */
            scanOffset = centralDirOffset;
            stopOffset = scanOffset + 6;

            while (true)
            {
                mRaf.seek(scanOffset);
                if (ZipEntry.readIntLE(mRaf) == CENSIG)
                {
                    break;
                }

                scanOffset++;
                if (scanOffset > stopOffset)
                {
                    throw new ZipException("Central Directory Entry not found");
                }
            }

            // If CDE is found then go and read all the entries
            rafs = new RAFStream(mRaf, scanOffset);
            bin  = new java.io.BufferedInputStream(rafs, 4096);
            for (int i = 0; i < numEntries; i++)
            {
                ZipEntry newEntry = new ZipEntry(ler, bin);
                mEntries.put(newEntry.getName(), newEntry);
            }
        }