zipfile.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 661 行 · 第 1/2 页

JAVA
661
字号
	 * @param the name. May contain directory components separated by
	 * slashes ('/').
	 * @return the zip entry, or null if no entry with that name exists.
	 */
	public ZipEntry getEntry(String name) {
		try {
			HashMap entries = getEntries();
			ZipEntry entry = (ZipEntry) entries.get(name);
			return entry != null ? (ZipEntry) entry.clone() : null;
		} catch (IOException ioe) {
			return null;
		}
	}

	//access should be protected by synchronized(raf)
	private byte[] locBuf = new byte[LOCHDR];

	/**
	 * Checks, if the local header of the entry at index i matches the
	 * central directory, and returns the offset to the data.
	 * 
	 * @param entry to check.
	 * @return the start offset of the (compressed) data.
	 *
	 * @exception IOException if a i/o error occured.
	 * @exception ZipException if the local header doesn't match the 
	 * central directory header
	 */
	private long checkLocalHeader(ZipEntry entry) throws IOException {
		synchronized (raf) {
			raf.seek(entry.offset);
			raf.readFully(locBuf);

			if (readLeInt(locBuf, 0) != LOCSIG)
				throw new ZipException("Wrong Local header signature: " + name);

			if (entry.getMethod() != readLeShort(locBuf, LOCHOW))
				throw new ZipException("Compression method mismatch: " + name);

			if (entry.getName().length() != readLeShort(locBuf, LOCNAM))
				throw new ZipException("file name length mismatch: " + name);

			int extraLen = entry.getName().length() + readLeShort(locBuf, LOCEXT);
			return entry.offset + LOCHDR + extraLen;
		}
	}

	/**
	 * Creates an input stream reading the given zip entry as
	 * uncompressed data.  Normally zip entry should be an entry
	 * returned by getEntry() or entries().
	 *
	 * @param entry the entry to create an InputStream for.
	 * @return the input stream.
	 *
	 * @exception IOException if a i/o error occured.
	 * @exception ZipException if the Zip archive is malformed.  
	 */
	public InputStream getInputStream(ZipEntry entry) throws IOException {
		HashMap entries = getEntries();
		String name = entry.getName();
		ZipEntry zipEntry = (ZipEntry) entries.get(name);
		if (zipEntry == null)
			throw new NoSuchElementException(name);

		long start = checkLocalHeader(zipEntry);
		int method = zipEntry.getMethod();
		InputStream is = new BufferedInputStream(new PartialInputStream(raf, start, zipEntry.getCompressedSize()));
		switch (method) {
			case ZipOutputStream.STORED :
				return is;
			case ZipOutputStream.DEFLATED :
				return new InflaterInputStream(is, new Inflater(true));
			default :
				throw new ZipException("Unknown compression method " + method);
		}
	}

	/**
	 * Returns the name of this zip file.
	 */
	public String getName() {
		return name;
	}

	/**
	 * Returns the number of entries in this zip file.
	 */
	public int size() {
		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 class PartialInputStream extends InputStream {
		private final RandomAccessBuffer raf;
		long filepos, end;

		public PartialInputStream(RandomAccessBuffer raf, long start, long len) {
			this.raf = raf;
			filepos = start;
			end = start + len;
		}

		public int available() {
			long amount = end - filepos;
			if (amount > Integer.MAX_VALUE)
				return Integer.MAX_VALUE;
			return (int) amount;
		}

		public int read() throws IOException {
			if (filepos == end)
				return -1;
			synchronized (raf) {
				raf.seek(filepos++);
				return raf.read();
			}
		}

		public int read(byte[] b, int off, int len) throws IOException {
			if (len > end - filepos) {
				len = (int) (end - filepos);
				if (len == 0)
					return -1;
			}
			synchronized (raf) {
				raf.seek(filepos);
				int count = raf.read(b, off, len);
				if (count > 0)
					filepos += len;
				return count;
			}
		}

		public long skip(long amount) {
			if (amount < 0)
				throw new IllegalArgumentException();
			if (amount > end - filepos)
				amount = end - filepos;
			filepos += amount;
			return amount;
		}
	}
	
	private static class RandomAccessFileBuffer extends RandomAccessBuffer {
		
		private final RandomAccessFile raf;
		
		public RandomAccessFileBuffer(RandomAccessFile raf) {
			this.raf = raf;
		}
		
		/**
		 * @see RandomAccessBuffer#seek(long)
		 */
		public void seek(long offset) throws IOException {
			raf.seek(offset);
		}
		/**
		 * @see RandomAccessBuffer#length()
		 */
		public long length() 
		throws IOException {
			return raf.length();
		}

		/**
		 * @see RandomAccessBuffer#readFully(byte[], int, int)
		 */
		public void readFully(byte[] data, int offset, int length)
		throws IOException {
			raf.readFully(data, offset, length);
		}

		/**
		 * @see RandomAccessBuffer#skipBytes(int)
		 */
		public int skipBytes(int count) throws EOFException, IOException {
			return raf.skipBytes(count);
		}

		/**
		 * @see RandomAccessBuffer#readFully(byte[])
		 */
		public void readFully(byte[] data) throws IOException {
			raf.readFully(data);
		}

		/**
		 * @see RandomAccessBuffer#close()
		 */
		public void close() 
		throws IOException {
			raf.close();
		}

		/**
		 * @see RandomAccessBuffer#read()
		 */
		public int read() throws IOException {
			return raf.read();
		}

		/**
		 * @see RandomAccessBuffer#read(byte[], int, int)
		 */
		public int read(byte[] data, int offset, int length)
			throws IOException {
			return raf.read(data, offset, length);
		}

	}
	
	private static class RandomAccessByteArrayBuffer extends RandomAccessBuffer {
		
		private final byte[] buffer;
		private int pos;
		private final int length;
		
		public RandomAccessByteArrayBuffer(byte[] buffer) {
			this.buffer = buffer;
			this.length = buffer.length;
			this.pos = 0;
		}
		
		/**
		 * @see RandomAccessBuffer#seek(long)
		 */
		public void seek(long offset) throws IOException {
			pos = (int)offset;
		}
		
		/**
		 * @see RandomAccessBuffer#length()
		 */
		public long length() 
		throws IOException {
			return length;
		}

		/**
		 * @see RandomAccessBuffer#readFully(byte[])
		 */
		public void readFully(byte[] data) throws IOException {
			readFully(data, 0, data.length);
		}

		/**
		 * @see RandomAccessBuffer#readFully(byte[], int, int)
		 */
		public void readFully(byte[] data, int offset, int len)
		throws IOException {
			if (pos + len <= length) {
				System.arraycopy(buffer, pos, data, offset, len);
				pos += len;
			} else {
				throw new EOFException();
			}
		}

		/**
		 * @see RandomAccessBuffer#skipBytes(int)
		 */
		public int skipBytes(int count) throws EOFException, IOException {
			if (count > 0) {
				count = Math.min(length - pos, count);
				pos += count;
				return count;
			} else {
				return 0;
			}
		}

		/**
		 * @see RandomAccessBuffer#close()
		 */
		public void close() 
		throws IOException {
		}

		/**
		 * @see RandomAccessBuffer#read()
		 */
		public int read() throws IOException {
			if (pos < length) {
				return buffer[pos++] & 0xFF;
			} else {
				return -1;
			}
		}

		/**
		 * @see RandomAccessBuffer#read(byte[], int, int)
		 */
		public int read(byte[] data, int offset, int len)
		throws IOException {
			if (pos < length) {
				len = Math.min(length - pos, len);
				System.arraycopy(buffer, pos, data, offset, len);
				pos += len;
				return len;
			} else {
				return -1;
			}
		}
	}
}

⌨️ 快捷键说明

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