⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zipfileindex.java

📁 是一款用JAVA 编写的编译器 具有很强的编译功能
💻 JAVA
📖 第 1 页 / 共 3 页
字号:

            return allDirs;
        }
        catch (IOException e) {
            return Collections.EMPTY_SET;
        }
        finally {
            lock.unlock();
        }
    }

    /**
     * Tests if a specific path exists in the zip.  This method will return true
     * for file entries and directories.
     *
     * @param path A path within the zip.
     * @return True if the path is a file or dir, false otherwise.
     */
    public boolean contains(String path) {
        lock.lock();
        try {
            checkIndex();
            return getZipIndexEntry(path) != null;
        }
        catch (IOException e) {
            return false;
        }
        finally {
            lock.unlock();
        }
    }
    
    public boolean isDirectory(String path) throws IOException {
        lock.lock();
        try {
            // The top level in a zip file is always a directory.
            if (path.length() == 0) {
                lastReferenceTimeStamp = System.currentTimeMillis();
                return true;
            }

            if (File.separatorChar != '/')
                path = path.replace('/', File.separatorChar);
            checkIndex();
            return directories.get(path) != null;
        }
        finally {
            lock.unlock();
        }
    }
    
    public long getLastModified(String path) throws IOException {
        lock.lock();
        try {
            ZipFileIndexEntry entry = getZipIndexEntry(path);
            if (entry == null)
                throw new FileNotFoundException();
            return entry.getLastModified();
        }
        finally {
            lock.unlock();
        }
    }
    
    public int length(String path) throws IOException {
        lock.lock();
        try {
            ZipFileIndexEntry entry = getZipIndexEntry(path);
            if (entry == null)
                throw new FileNotFoundException();

            if (entry.isDir) {
                return 0;
            }

            byte[] header = getHeader(entry);
            // entry is not compressed?
            if (get2ByteLittleEndian(header, 8) == 0) {
                return entry.compressedSize;
            } else {
                return entry.size;
            }
        }
        finally {
            lock.unlock();
        }
    }
    
    public byte[] read(String path) throws IOException {
        lock.lock();
        try {
            ZipFileIndexEntry entry = getZipIndexEntry(path);
            if (entry == null)
                throw new FileNotFoundException(MessageFormat.format("Path not found in ZIP: {0}", path));
            return read(entry);
        }
        finally {
            lock.unlock();
        }
    }
    
    public byte[] read(ZipFileIndexEntry entry) throws IOException {
        lock.lock();
        try {
            openFile();
            byte[] result = readBytes(entry);
            closeFile();
            return result;
        }
        finally {
            lock.unlock();
        }
    }
    
    public int read(String path, byte[] buffer) throws IOException {
        lock.lock();
        try {
            ZipFileIndexEntry entry = getZipIndexEntry(path);
            if (entry == null)
                throw new FileNotFoundException();
            return read(entry, buffer);
        }
        finally {
            lock.unlock();
        }
    }
    
    public int read(ZipFileIndexEntry entry, byte[] buffer)
            throws IOException {
        lock.lock();
        try {
            int result = readBytes(entry, buffer);
            return result;
        }
        finally {
            lock.unlock();
        }
    }
    
    private byte[] readBytes(ZipFileIndexEntry entry) throws IOException {
        byte[] header = getHeader(entry);
        int csize = entry.compressedSize;
        byte[] cbuf = new byte[csize];
        zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
        zipRandomFile.readFully(cbuf, 0, csize);
        
        // is this compressed - offset 8 in the ZipEntry header
        if (get2ByteLittleEndian(header, 8) == 0)
            return cbuf;
        
        int size = entry.size;
        byte[] buf = new byte[size];
        if (inflate(cbuf, buf) != size)
            throw new ZipException("corrupted zip file");
        
        return buf;
    }
    
    /**
     *
     */
    private int readBytes(ZipFileIndexEntry entry, byte[] buffer) throws IOException {
        byte[] header = getHeader(entry);
        
        // entry is not compressed?
        if (get2ByteLittleEndian(header, 8) == 0) {
            zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
            int offset = 0;
            int size = buffer.length;
            while (offset < size) {
                int count = zipRandomFile.read(buffer, offset, size - offset);
                if (count == -1)
                    break;
                offset += count;
            }
            return entry.size;
        }
        
        int csize = entry.compressedSize;
        byte[] cbuf = new byte[csize];
        zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
        zipRandomFile.readFully(cbuf, 0, csize);
        
        int count = inflate(cbuf, buffer);
        if (count == -1)
            throw new ZipException("corrupted zip file");
        
        return entry.size;
    }
    
    //----------------------------------------------------------------------------
    // Zip utilities
    //----------------------------------------------------------------------------
    
    private byte[] getHeader(ZipFileIndexEntry entry) throws IOException {
        zipRandomFile.seek(entry.offset);
        byte[] header = new byte[30];
        zipRandomFile.readFully(header);
        if (get4ByteLittleEndian(header, 0) != 0x04034b50)
            throw new ZipException("corrupted zip file");
        if ((get2ByteLittleEndian(header, 6) & 1) != 0)
            throw new ZipException("encrypted zip file"); // offset 6 in the header of the ZipFileEntry
        return header;
    }
    
  /*
   * Inflate using the java.util.zip.Inflater class
   */
    private static Inflater inflater;
    private int inflate(byte[] src, byte[] dest) {
        
        // construct the inflater object or reuse an existing one
        if (inflater == null)
            inflater = new Inflater(true);
        
        synchronized (inflater) {
            inflater.reset();
            inflater.setInput(src);
            try {
                return inflater.inflate(dest);
            } catch (DataFormatException ex) {
                return -1;
            }
        }
    }
    
    /**
     * return the two bytes buf[pos], buf[pos+1] as an unsigned integer in little
     * endian format.
     */
    private static int get2ByteLittleEndian(byte[] buf, int pos) {
        return (buf[pos] & 0xFF) + ((buf[pos+1] & 0xFF) << 8);
    }
    
    /**
     * return the 4 bytes buf[i..i+3] as an integer in little endian format.
     */
    private static int get4ByteLittleEndian(byte[] buf, int pos) {
        return (buf[pos] & 0xFF) + ((buf[pos + 1] & 0xFF) << 8) +
                ((buf[pos + 2] & 0xFF) << 16) + ((buf[pos + 3] & 0xFF) << 24);
    }
    
    /* ----------------------------------------------------------------------------
     * ZipDirectory
     * ----------------------------------------------------------------------------*/
    
    private class ZipDirectory {
        private String lastDir;
        private int lastStart;
        private int lastLen;
        
        byte[] zipDir;
        RandomAccessFile zipRandomFile = null;
        ZipFileIndex zipFileIndex = null;
        
        public ZipDirectory(RandomAccessFile zipRandomFile, long start, long end, ZipFileIndex index) throws IOException {
            this.zipRandomFile = zipRandomFile;
            this.zipFileIndex = index;
            
            findCENRecord(start, end);
        }
        
        /*
         * Reads zip file central directory.
         * For more details see readCEN in zip_util.c from the JDK sources.
         * This is a Java port of that function.
         */
        private void findCENRecord(long start, long end) throws IOException {
            long totalLength = end - start;
            int endbuflen = 1024;
            byte[] endbuf = new byte[endbuflen];
            long endbufend = end - start;
            
            // There is a variable-length field after the dir offset record. We need to do consequential search.
            while (endbufend >= 22) {
                if (endbufend < endbuflen)
                    endbuflen = (int)endbufend;
                long endbufpos = endbufend - endbuflen;
                zipRandomFile.seek(start + endbufpos);
                zipRandomFile.readFully(endbuf, 0, endbuflen);
                int i = endbuflen - 22;
                while (i >= 0 &&
                        !(endbuf[i] == 0x50 &&
                        endbuf[i + 1] == 0x4b &&
                        endbuf[i + 2] == 0x05 &&
                        endbuf[i + 3] == 0x06 &&
                        endbufpos + i + 22 +
                        get2ByteLittleEndian(endbuf, i + 20) == totalLength)) {
                    i--;
                }
                
                if (i >= 0) {
                    zipDir = new byte[get4ByteLittleEndian(endbuf, i + 12) + 2];
                    zipDir[0] = endbuf[i + 10];
                    zipDir[1] = endbuf[i + 11];
                    zipRandomFile.seek(start + get4ByteLittleEndian(endbuf, i + 16));
                    zipRandomFile.readFully(zipDir, 2, zipDir.length - 2);
                    return;
                } else {
                    endbufend = endbufpos + 21;
                }
            }
            throw new ZipException("cannot read zip file");
        }
        private void buildIndex() throws IOException {
            int entryCount = get2ByteLittleEndian(zipDir, 0);
            
            entries = new ZipFileIndexEntry[entryCount];
            // Add each of the files
            if (entryCount > 0) {
                directories = new HashMap();
                ArrayList<ZipFileIndexEntry> entryList = new ArrayList<ZipFileIndexEntry>();
                int pos = 2;
                for (int i = 0; i < entryCount; i++) {
                    pos = readEntry(pos, entryList, directories);
                }
                
                // Add the accumulated dirs into the same list
                Iterator i = directories.keySet().iterator();
                while (i.hasNext()) {
                    ZipFileIndexEntry zipFileIndexEntry = new ZipFileIndexEntry( (String) i.next());
                    zipFileIndexEntry.isDir = true;
                    entryList.add(zipFileIndexEntry);
                }
                
                entries = entryList.toArray(new ZipFileIndexEntry[entryList.size()]);
                Arrays.sort(entries);
            } else {
                cleanupState();
            }
        }
        
        private int readEntry(int pos, List entryList,
                Map directories) throws IOException {
            if (get4ByteLittleEndian(zipDir, pos) != 0x02014b50) {
                throw new ZipException("cannot read zip file entry");
            }

            int dirStart = pos + 46;
            int fileStart = dirStart;
            int fileEnd = fileStart + get2ByteLittleEndian(zipDir, pos + 28);
            
            if (zipFileIndex.symbolFilePrefixLength != 0 &&
                    ((fileEnd - fileStart) >= symbolFilePrefixLength)) {
                dirStart += zipFileIndex.symbolFilePrefixLength;
               fileStart += zipFileIndex.symbolFilePrefixLength;
            }

            // Use the OS's path separator. Keep the position of the last one.
            for (int index = fileStart; index < fileEnd; index++) {
                byte nextByte = zipDir[index];
                if (nextByte == (byte)'\\' || nextByte == (byte)'/') {
                    zipDir[index] = (byte)File.separatorChar;
                    fileStart = index + 1;
                }
            }
            
            String directory = null;
            if (fileStart == dirStart)
                directory = "";
            else if (lastDir != null && lastLen == fileStart - dirStart - 1) {
                int index = lastLen - 1;
                while (zipDir[lastStart + index] == zipDir[dirStart + index]) {
                    if (index == 0) {
                        directory = lastDir;
                        break;
                    }
                    index--;
                }
            }
            
            // Sub directories
            if (directory == null) {
                lastStart = dirStart;
                lastLen = fileStart - dirStart - 1;
                
                directory = new String(zipDir, dirStart, lastLen, "UTF-8").intern();
                lastDir = directory;
                
                // Enter also all the parent directories
                String tempDirectory = directory;

                while (directories.get(tempDirectory) == null) {
                    directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex));
                    int separator = tempDirectory.lastIndexOf(File.separatorChar);
                    if (separator == -1)
                        break;
                    tempDirectory = tempDirectory.substring(0, separator);
                }
            }
            else {
                directory = directory.intern();
                if (directories.get(directory) == null) {
                    directories.put(directory, new DirectoryEntry(directory, zipFileIndex));
                }
            }
            
            // For each dir create also a file
            if (fileStart != fileEnd) {
                ZipFileIndexEntry entry = new ZipFileIndexEntry(directory,
                        new String(zipDir, fileStart, fileEnd - fileStart, "UTF-8"));

                entry.setNativeTime(get4ByteLittleEndian(zipDir, pos + 12));
                entry.compressedSize = get4ByteLittleEndian(zipDir, pos + 20);
                entry.size = get4ByteLittleEndian(zipDir, pos + 24);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -