zipfile.java

来自「linux下建立JAVA虚拟机的源码KAFFE」· Java 代码 · 共 673 行 · 第 1/2 页

JAVA
673
字号
    catch (IOException ioe)      {	return EmptyEnumeration.getInstance();      }  }  /**   * Checks that the ZipFile is still open and reads entries when necessary.   *   * @exception IllegalStateException when the ZipFile has already been closed.   * @exception IOException when the entries could not be read.   */  private HashMap getEntries() throws IOException  {    synchronized(raf)      {	checkClosed();	if (entries == null)	  readEntries();	return entries;      }  }  /**   * Searches for a zip entry in this archive with the given name.   *   * @param name the name. May contain directory components separated by   * slashes ('/').   * @return the zip entry, or null if no entry with that name exists.   *   * @exception IllegalStateException when the ZipFile has already been closed   */  public ZipEntry getEntry(String name)  {    checkClosed();    try      {	HashMap entries = getEntries();	ZipEntry entry = (ZipEntry) entries.get(name);        // If we didn't find it, maybe it's a directory.        if (entry == null && !name.endsWith("/"))            entry = (ZipEntry) entries.get(name + '/');	return entry != null ? new ZipEntry(entry, name) : null;      }    catch (IOException ioe)      {	return null;      }  }  /**   * Creates an input stream reading the given zip entry as   * uncompressed data.  Normally zip entry should be an entry   * returned by getEntry() or entries().   *   * This implementation returns null if the requested entry does not   * exist.  This decision is not obviously correct, however, it does   * appear to mirror Sun's implementation, and it is consistant with   * their javadoc.  On the other hand, the old JCL book, 2nd Edition,   * claims that this should return a "non-null ZIP entry".  We have   * chosen for now ignore the old book, as modern versions of Ant (an   * important application) depend on this behaviour.  See discussion   * in this thread:   * http://gcc.gnu.org/ml/java-patches/2004-q2/msg00602.html   *   * @param entry the entry to create an InputStream for.   * @return the input stream, or null if the requested entry does not exist.   *   * @exception IllegalStateException when the ZipFile has already been closed   * @exception IOException if a i/o error occured.   * @exception ZipException if the Zip archive is malformed.     */  public InputStream getInputStream(ZipEntry entry) throws IOException  {    checkClosed();    HashMap entries = getEntries();    String name = entry.getName();    ZipEntry zipEntry = (ZipEntry) entries.get(name);    if (zipEntry == null)      return null;    PartialInputStream inp = new PartialInputStream(raf, 1024);    inp.seek(zipEntry.offset);    if (inp.readLeInt() != LOCSIG)      throw new ZipException("Wrong Local header signature: " + name);    inp.skip(4);    if (zipEntry.getMethod() != inp.readLeShort())      throw new ZipException("Compression method mismatch: " + name);    inp.skip(16);    int nameLen = inp.readLeShort();    int extraLen = inp.readLeShort();    inp.skip(nameLen + extraLen);    inp.setLength(zipEntry.getCompressedSize());    int method = zipEntry.getMethod();    switch (method)      {      case ZipOutputStream.STORED:	return inp;      case ZipOutputStream.DEFLATED:	return new InflaterInputStream(inp, new Inflater(true));      default:	throw new ZipException("Unknown compression method " + method);      }  }    /**   * Returns the (path) name of this zip file.   */  public String getName()  {    return name;  }  /**   * Returns the number of entries in this zip file.   *   * @exception IllegalStateException when the ZipFile has already been closed   */  public int size()  {    checkClosed();        try      {	return getEntries().size();      }    catch (IOException ioe)      {	return 0;      }  }    private static class ZipEntryEnumeration implements Enumeration  {    private final Iterator elements;    public ZipEntryEnumeration(Iterator elements)    {      this.elements = elements;    }    public boolean hasMoreElements()    {      return elements.hasNext();    }    public Object nextElement()    {      /* We return a clone, just to be safe that the user doesn't       * change the entry.         */      return ((ZipEntry)elements.next()).clone();    }  }  private static final class PartialInputStream extends InputStream  {    private final RandomAccessFile raf;    private final byte[] buffer;    private long bufferOffset;    private int pos;    private long end;    public PartialInputStream(RandomAccessFile raf, int bufferSize)      throws IOException    {      this.raf = raf;      buffer = new byte[bufferSize];      bufferOffset = -buffer.length;      pos = buffer.length;      end = raf.length();    }    void setLength(long length)    {      end = bufferOffset + pos + length;    }    private void fillBuffer() throws IOException    {      synchronized (raf)        {          raf.seek(bufferOffset);          raf.readFully(buffer, 0, (int) Math.min(buffer.length, end - bufferOffset));        }    }        public int available()    {      long amount = end - (bufferOffset + pos);      if (amount > Integer.MAX_VALUE)	return Integer.MAX_VALUE;      return (int) amount;    }        public int read() throws IOException    {      if (bufferOffset + pos >= end)	return -1;      if (pos == buffer.length)        {          bufferOffset += buffer.length;          pos = 0;          fillBuffer();        }      return buffer[pos++] & 0xFF;    }    public int read(byte[] b, int off, int len) throws IOException    {      if (len > end - (bufferOffset + pos))	{	  len = (int) (end - (bufferOffset + pos));	  if (len == 0)	    return -1;	}      int totalBytesRead = Math.min(buffer.length - pos, len);      System.arraycopy(buffer, pos, b, off, totalBytesRead);      pos += totalBytesRead;      off += totalBytesRead;      len -= totalBytesRead;      while (len > 0)        {          bufferOffset += buffer.length;          pos = 0;          fillBuffer();          int remain = Math.min(buffer.length, len);          System.arraycopy(buffer, pos, b, off, remain);          pos += remain;          off += remain;          len -= remain;          totalBytesRead += remain;        }      return totalBytesRead;    }    public long skip(long amount) throws IOException    {      if (amount < 0)	return 0;      if (amount > end - (bufferOffset + pos))	amount = end - (bufferOffset + pos);      seek(bufferOffset + pos + amount);      return amount;    }    void seek(long newpos) throws IOException    {      long offset = newpos - bufferOffset;      if (offset >= 0 && offset <= buffer.length)        {          pos = (int) offset;        }      else        {          bufferOffset = newpos;          pos = 0;          fillBuffer();        }    }    void readFully(byte[] buf) throws IOException    {      if (read(buf, 0, buf.length) != buf.length)        throw new EOFException();    }    void readFully(byte[] buf, int off, int len) throws IOException    {      if (read(buf, off, len) != len)        throw new EOFException();    }    int readLeShort() throws IOException    {      int b0 = read();      int b1 = read();      if (b1 == -1)        throw new EOFException();      return (b0 & 0xff) | (b1 & 0xff) << 8;    }    int readLeInt() throws IOException    {      int b0 = read();      int b1 = read();      int b2 = read();      int b3 = read();      if (b3 == -1)        throw new EOFException();      return ((b0 & 0xff) | (b1 & 0xff) << 8)            | ((b2 & 0xff) | (b3 & 0xff) << 8) << 16;    }    String readString(int length) throws IOException    {      if (length > end - (bufferOffset + pos))        throw new EOFException();      try        {          if (buffer.length - pos >= length)            {              String s = new String(buffer, pos, length, "UTF-8");              pos += length;              return s;            }          else            {              byte[] b = new byte[length];              readFully(b);              return new String(b, 0, length, "UTF-8");            }        }      catch (UnsupportedEncodingException uee)        {          throw new AssertionError(uee);        }    }  }}

⌨️ 快捷键说明

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