Java压缩包解压到指定文件
在获得一个以Zip格式压缩的文件之后,需要将其进行解压缩,还原成压缩前的文件。若是使用Java自带的压缩工具包来实现解压缩文件到指定文件夹的功能,因为jdk提供的zip只能按UTF-8格式处理,而Windows系统中文件名是以GBK方式编码的,所以如果是解压一个包含中文文件名的zip包,会报非法参数异常,如图所示:
所以要实现解压缩,就得对DeflaterOutputStream.java、InflaterInputStream.java、ZipConstants.java、ZipEntry.java、ZipInputStream.java以及ZipOutputStream.java这些相关的类进行修改,过程如下:
- 因为从 J2SE 1.4 开始,Java 编译器不再支持 import 进未命包名的类、接口,所以在创建的Java项目中,一定要新建一个自己定义的包,包命名的格式一般为学校域名的逆序+自己的网名,比如cn.edu.xidian.crytoll。
- 在包内新建DeflaterOutputStream类,代码如下:
DeflaterOutputStream.java:
- package cn.edu.xdian.crytoll;
- import java.io.FilterOutputStream;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.util.zip.Deflater;
- /**
- * This class implements an output stream filter for compressing data in
- * the "deflate" compression format. It is also used as the basis for other
- * types of compression filters, such as GZIPOutputStream.
- *
- * @see Deflater
- * @version 1.36, 03/13/06
- * @author David Connelly
- */
- public
- class DeflaterOutputStream extends FilterOutputStream {
- /**
- * Compressor for this stream.
- */
- protected Deflater def;
- /**
- * Output buffer for writing compressed data.
- */
- protected byte[] buf;
- /**
- * Indicates that the stream has been closed.
- */
- private boolean closed = false;
- /**
- * Creates a new output stream with the specified compressor and
- * buffer size.
- * @param out the output stream
- * @param def the compressor ("deflater")
- * @param size the output buffer size
- * @exception IllegalArgumentException if size is <= 0
- */
- public DeflaterOutputStream(OutputStream out, Deflater def, int size) {
- super(out);
- if (out == null || def == null) {
- throw new NullPointerException();
- } else if (size <= 0) {
- throw new IllegalArgumentException("buffer size <= 0");
- }
- this.def = def;
- buf = new byte[size];
- }
- /**
- * Creates a new output stream with the specified compressor and
- * a default buffer size.
- * @param out the output stream
- * @param def the compressor ("deflater")
- */
- public DeflaterOutputStream(OutputStream out, Deflater def) {
- this(out, def, 512);
- }
- boolean usesDefaultDeflater = false;
- /**
- * Creates a new output stream with a default compressor and buffer size.
- * @param out the output stream
- */
- public DeflaterOutputStream(OutputStream out) {
- this(out, new Deflater());
- usesDefaultDeflater = true;
- }
- /**
- * Writes a byte to the compressed output stream. This method will
- * block until the byte can be written.
- * @param b the byte to be written
- * @exception IOException if an I/O error has occurred
- */
- public void write(int b) throws IOException {
- byte[] buf = new byte[1];
- buf[0] = (byte)(b & 0xff);
- write(buf, 0, 1);
- }
- /**
- * Writes an array of bytes to the compressed output stream. This
- * method will block until all the bytes are written.
- * @param b the data to be written
- * @param off the start offset of the data
- * @param len the length of the data
- * @exception IOException if an I/O error has occurred
- */
- public void write(byte[] b, int off, int len) throws IOException {
- if (def.finished()) {
- throw new IOException("write beyond end of stream");
- }
- if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return;
- }
- if (!def.finished()) {
- // Deflate no more than stride bytes at a time. This avoids
- // excess copying in deflateBytes (see Deflater.c)
- int stride = buf.length;
- for (int i = 0; i < len; i+= stride) {
- def.setInput(b, off + i, Math.min(stride, len - i));
- while (!def.needsInput()) {
- deflate();
- }
- }
- }
- }
- /**
- * Finishes writing compressed data to the output stream without closing
- * the underlying stream. Use this method when applying multiple filters
- * in succession to the same output stream.
- * @exception IOException if an I/O error has occurred
- */
- public void finish() throws IOException {
- if (!def.finished()) {
- def.finish();
- while (!def.finished()) {
- deflate();
- }
- }
- }
- /**
- * Writes remaining compressed data to the output stream and closes the
- * underlying stream.
- * @exception IOException if an I/O error has occurred
- */
- public void close() throws IOException {
- if (!closed) {
- finish();
- if (usesDefaultDeflater)
- def.end();
- out.close();
- closed = true;
- }
- }
- /**
- * Writes next block of compressed data to the output stream.
- * @throws IOException if an I/O error has occurred
- */
- protected void deflate() throws IOException {
- int len = def.deflate(buf, 0, buf.length);
- if (len > 0) {
- out.write(buf, 0, len);
- }
- }
- }
3. 在包内新建InflaterInputStream类,代码如下:
InflaterInputStream.java:
- package cn.edu.xdian.crytoll;
- import java.io.EOFException;
- import java.io.FilterInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.zip.DataFormatException;
- import java.util.zip.Inflater;
- import java.util.zip.ZipException;
- /**
- * This class implements a stream filter for uncompressing data in the
- * "deflate" compression format. It is also used as the basis for other
- * decompression filters, such as GZIPInputStream.
- *
- * @see Inflater
- * @version 1.40, 04/07/06
- * @author David Connelly
- */
- public
- class InflaterInputStream extends FilterInputStream {
- /**
- * Decompressor for this stream.
- */
- protected Inflater inf;
- /**
- * Input buffer for decompression.
- */
- protected byte[] buf;
- /**
- * Length of input buffer.
- */
- protected int len;
- private boolean closed = false;
- // this flag is set to true after EOF has reached
- private boolean reachEOF = false;
- /**
- * Check to make sure that this stream has not been closed
- */
- private void ensureOpen() throws IOException {
- if (closed) {
- throw new IOException("Stream closed");
- }
- }
- /**
- * Creates a new input stream with the specified decompressor and
- * buffer size.
- * @param in the input stream
- * @param inf the decompressor ("inflater")
- * @param size the input buffer size
- * @exception IllegalArgumentException if size is <= 0
- */
- public InflaterInputStream(InputStream in, Inflater inf, int size) {
- super(in);
- if (in == null || inf == null) {
- throw new NullPointerException();
- } else if (size <= 0) {
- throw new IllegalArgumentException("buffer size <= 0");
- }
- this.inf = inf;
- buf = new byte[size];
- }
- /**
- * Creates a new input stream with the specified decompressor and a
- * default buffer size.
- * @param in the input stream
- * @param inf the decompressor ("inflater")
- */
- public InflaterInputStream(InputStream in, Inflater inf) {
- this(in, inf, 512);
- }
- boolean usesDefaultInflater = false;
- /**
- * Creates a new input stream with a default decompressor and buffer size.
- * @param in the input stream
- */
- public InflaterInputStream(InputStream in) {
- this(in, new Inflater());
- usesDefaultInflater = true;
- }
- private byte[] singleByteBuf = new byte[1];
- /**
- * Reads a byte of uncompressed data. This method will block until
- * enough input is available for decompression.
- * @return the byte read, or -1 if end of compressed input is reached
- * @exception IOException if an I/O error has occurred
- */
- public int read() throws IOException {
- ensureOpen();
- return read(singleByteBuf, 0, 1) == -1 ? -1 : singleByteBuf[0] & 0xff;
- }
- /**
- * Reads uncompressed data into an array of bytes. If <code>len</code> is not
- * zero, the method will block until some input can be decompressed; otherwise,
- * no bytes are read and <code>0</code> is returned.
- * @param b the buffer into which the data is read
- * @param off the start offset in the destination array <code>b</code>
- * @param len the maximum number of bytes read
- * @return the actual number of bytes read, or -1 if the end of the
- * compressed input is reached or a preset dictionary is needed
- * @exception NullPointerException If <code>b</code> is <code>null</code>.
- * @exception IndexOutOfBoundsException If <code>off</code> is negative,
- * <code>len</code> is negative, or <code>len</code> is greater than
- * <code>b.length - off</code>
- * @exception ZipException if a ZIP format error has occurred
- * @exception IOException if an I/O error has occurred
- */
- public int read(byte[] b, int off, int len) throws IOException {
- ensureOpen();
- if (b == null) {
- throw new NullPointerException();
- } else if (off < 0 || len < 0 || len > b.length - off) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return 0;
- }
- try {
- int n;
- while ((n = inf.inflate(b, off, len)) == 0) {
- if (inf.finished() || inf.needsDictionary()) {
- reachEOF = true;
- return -1;
- }
- if (inf.needsInput()) {
- fill();
- }
- }
- return n;
- } catch (DataFormatException e) {
- String s = e.getMessage();
- throw new ZipException(s != null ? s : "Invalid ZLIB data format");
- }
- }
- /**
- * Returns 0 after EOF has been reached, otherwise always return 1.
- * <p>
- * Programs should not count on this method to return the actual number
- * of bytes that could be read without blocking.
- *
- * @return 1 before EOF and 0 after EOF.
- * @exception IOException if an I/O error occurs.
- *
- */
- public int available() throws IOException {
- ensureOpen();
- if (reachEOF) {
- return 0;
- } else {
- return 1;
- }
- }
- private byte[] b = new byte[512];
- /**
- * Skips specified number of bytes of uncompressed data.
- * @param n the number of bytes to skip
- * @return the actual number of bytes skipped.
- * @exception IOException if an I/O error has occurred
- * @exception IllegalArgumentException if n < 0
- */
- public long skip(long n) throws IOException {
- if (n < 0) {
- throw new IllegalArgumentException("negative skip length");
- }
- ensureOpen();
- int max = (int)Math.min(n, Integer.MAX_VALUE);
- int total = 0;
- while (total < max) {
- int len = max - total;
- if (len > b.length) {
- len = b.length;
- }
- len = read(b, 0, len);
- if (len == -1) {
- reachEOF = true;
- break;
- }
- total += len;
- }
- return total;
- }
- /**
- * Closes this input stream and releases any system resources associated
- * with the stream.
- * @exception IOException if an I/O error has occurred
- */
- public void close() throws IOException {
- if (!closed) {
- if (usesDefaultInflater)
- inf.end();
- in.close();
- closed = true;
- }
- }
- /**
- * Fills input buffer with more data to decompress.
- * @exception IOException if an I/O error has occurred
- */
- protected void fill() throws IOException {
- ensureOpen();
- len = in.read(buf, 0, buf.length);
- if (len == -1) {
- throw new EOFException("Unexpected end of ZLIB input stream");
- }
- inf.setInput(buf, 0, len);
- }
- /**
- * Tests if this input stream supports the <code>mark</code> and
- * <code>reset</code> methods. The <code>markSupported</code>
- * method of <code>InflaterInputStream</code> returns
- * <code>false</code>.
- *
- * @return a <code>boolean</code> indicating if this stream type supports
- * the <code>mark</code> and <code>reset</code> methods.
- * @see java.io.InputStream#mark(int)
- * @see java.io.InputStream#reset()
- */
- public boolean markSupported() {
- return false;
- }
- /**
- * Marks the current position in this input stream.
- *
- * <p> The <code>mark</code> method of <code>InflaterInputStream</code>
- * does nothing.
- *
- * @param readlimit the maximum limit of bytes that can be read before
- * the mark position becomes invalid.
- * @see java.io.InputStream#reset()
- */
- public synchronized void mark(int readlimit) {
- }
- /**
- * Repositions this stream to the position at the time the
- * <code>mark</code> method was last called on this input stream.
- *
- * <p> The method <code>reset</code> for class
- * <code>InflaterInputStream</code> does nothing except throw an
- * <code>IOException</code>.
- *
- * @exception IOException if this method is invoked.
- * @see java.io.InputStream#mark(int)
- * @see java.io.IOException
- */
- public synchronized void reset() throws IOException {
- throw new IOException("mark/reset not supported");
- }
- }
4. 在包中新建ZipConstants接口,代码如下:
ZipConstants.java:
- package cn.edu.xdian.crytoll;
- interface ZipConstants {
- /*
- * Header signatures
- */
- static long LOCSIG = 0x04034b50L; // "PK\003\004"
- static long EXTSIG = 0x08074b50L; // "PK\007\008"
- static long CENSIG = 0x02014b50L; // "PK\001\002"
- static long ENDSIG = 0x06054b50L; // "PK\005\006"
- /*
- * Header sizes in bytes (including signatures)
- */
- static final int LOCHDR = 30; // LOC header size
- static final int EXTHDR = 16; // EXT header size
- static final int CENHDR = 46; // CEN header size
- static final int ENDHDR = 22; // END header size
- /*
- * Local file (LOC) header field offsets
- */
- static final int LOCVER = 4; // version needed to extract
- static final int LOCFLG = 6; // general purpose bit flag
- static final int LOCHOW = 8; // compression method
- static final int LOCTIM = 10; // modification time
- static final int LOCCRC = 14; // uncompressed file crc-32 value
- static final int LOCSIZ = 18; // compressed size
- static final int LOCLEN = 22; // uncompressed size
- static final int LOCNAM = 26; // filename length
- static final int LOCEXT = 28; // extra field length
- /*
- * Extra local (EXT) header field offsets
- */
- static final int EXTCRC = 4; // uncompressed file crc-32 value
- static final int EXTSIZ = 8; // compressed size
- static final int EXTLEN = 12; // uncompressed size
- /*
- * Central directory (CEN) header field offsets
- */
- static final int CENVEM = 4; // version made by
- static final int CENVER = 6; // version needed to extract
- static final int CENFLG = 8; // encrypt, decrypt flags
- static final int CENHOW = 10; // compression method
- static final int CENTIM = 12; // modification time
- static final int CENCRC = 16; // uncompressed file crc-32 value
- static final int CENSIZ = 20; // compressed size
- static final int CENLEN = 24; // uncompressed size
- static final int CENNAM = 28; // filename length
- static final int CENEXT = 30; // extra field length
- static final int CENCOM = 32; // comment length
- static final int CENDSK = 34; // disk number start
- static final int CENATT = 36; // internal file attributes
- static final int CENATX = 38; // external file attributes
- static final int CENOFF = 42; // LOC header offset
- /*
- * End of central directory (END) header field offsets
- */
- static final int ENDSUB = 8; // number of entries on this disk
- static final int ENDTOT = 10; // total number of entries
- static final int ENDSIZ = 12; // central directory size in bytes
- static final int ENDOFF = 16; // offset of first CEN header
- static final int ENDCOM = 20; // zip file comment length
- }
- 在包中新建ZipEntry类,代码如下:
ZipEntry.java:
- package cn.edu.xdian.crytoll;
- import java.util.Date;
- /**
- * This class is used to represent a ZIP file entry.
- *
- * @version 1.42, 01/02/08
- * @author David Connelly
- */
- public
- class ZipEntry implements ZipConstants, Cloneable {
- String name; // entry name
- long time = -1; // modification time (in DOS time)
- long crc = -1; // crc-32 of entry data
- long size = -1; // uncompressed size of entry data
- long csize = -1; // compressed size of entry data
- int method = -1; // compression method
- byte[] extra; // optional extra field data for entry
- String comment; // optional comment string for entry
- /**
- * Compression method for uncompressed entries.
- */
- public static final int STORED = 0;
- /**
- * Compression method for compressed (deflated) entries.
- */
- public static final int DEFLATED = 8;
- static {
- /* Zip library is loaded from System.initializeSystemClass */
- //initIDs();
- }
- private static native void initIDs();
- /**
- * Creates a new zip entry with the specified name.
- *
- * @param name the entry name
- * @exception NullPointerException if the entry name is null
- * @exception IllegalArgumentException if the entry name is longer than
- * 0xFFFF bytes
- */
- public ZipEntry(String name) {
- if (name == null) {
- throw new NullPointerException();
- }
- if (name.length() > 0xFFFF) {
- throw new IllegalArgumentException("entry name too long");
- }
- this.name = name;
- }
- /**
- * Creates a new zip entry with fields taken from the specified
- * zip entry.
- * @param e a zip Entry object
- */
- public ZipEntry(ZipEntry e) {
- name = e.name;
- time = e.time;
- crc = e.crc;
- size = e.size;
- csize = e.csize;
- method = e.method;
- extra = e.extra;
- comment = e.comment;
- }
- /*
- * Creates a new zip entry for the given name with fields initialized
- * from the specified jzentry data.
- */
- ZipEntry(String name, long jzentry) {
- this.name = name;
- initFields(jzentry);
- }
- private native void initFields(long jzentry);
- /*
- * Creates a new zip entry with fields initialized from the specified
- * jzentry data.
- */
- ZipEntry(long jzentry) {
- initFields(jzentry);
- }
- /**
- * Returns the name of the entry.
- * @return the name of the entry
- */
- public String getName() {
- return name;
- }
- /**
- * Sets the modification time of the entry.
- * @param time the entry modification time in number of milliseconds
- * since the epoch
- * @see #getTime()
- */
- public void setTime(long time) {
- this.time = javaToDosTime(time);
- }
- /**
- * Returns the modification time of the entry, or -1 if not specified.
- * @return the modification time of the entry, or -1 if not specified
- * @see #setTime(long)
- */
- public long getTime() {
- return time != -1 ? dosToJavaTime(time) : -1;
- }
- /**
- * Sets the uncompressed size of the entry data.
- * @param size the uncompressed size in bytes
- * @exception IllegalArgumentException if the specified size is less
- * than 0 or greater than 0xFFFFFFFF bytes
- * @see #getSize()
- */
- public void setSize(long size) {
- if (size < 0 || size > 0xFFFFFFFFL) {
- throw new IllegalArgumentException("invalid entry size");
- }
- this.size = size;
- }
- /**
- * Returns the uncompressed size of the entry data, or -1 if not known.
- * @return the uncompressed size of the entry data, or -1 if not known
- * @see #setSize(long)
- */
- public long getSize() {
- return size;
- }
- /**
- * Returns the size of the compressed entry data, or -1 if not known.
- * In the case of a stored entry, the compressed size will be the same
- * as the uncompressed size of the entry.
- * @return the size of the compressed entry data, or -1 if not known
- * @see #setCompressedSize(long)
- */
- public long getCompressedSize() {
- return csize;
- }
- /**
- * Sets the size of the compressed entry data.
- * @param csize the compressed size to set to
- * @see #getCompressedSize()
- */
- public void setCompressedSize(long csize) {
- this.csize = csize;
- }
- /**
- * Sets the CRC-32 checksum of the uncompressed entry data.
- * @param crc the CRC-32 value
- * @exception IllegalArgumentException if the specified CRC-32 value is
- * less than 0 or greater than 0xFFFFFFFF
- * @see #getCrc()
- */
- public void setCrc(long crc) {
- if (crc < 0 || crc > 0xFFFFFFFFL) {
- throw new IllegalArgumentException("invalid entry crc-32");
- }
- this.crc = crc;
- }
- /**
- * Returns the CRC-32 checksum of the uncompressed entry data, or -1 if
- * not known.
- * @return the CRC-32 checksum of the uncompressed entry data, or -1 if
- * not known
- * @see #setCrc(long)
- */
- public long getCrc() {
- return crc;
- }
- /**
- * Sets the compression method for the entry.
- * @param method the compression method, either STORED or DEFLATED
- * @exception IllegalArgumentException if the specified compression
- * method is invalid
- * @see #getMethod()
- */
- public void setMethod(int method) {
- if (method != STORED && method != DEFLATED) {
- throw new IllegalArgumentException("invalid compression method");
- }
- this.method = method;
- }
- /**
- * Returns the compression method of the entry, or -1 if not specified.
- * @return the compression method of the entry, or -1 if not specified
- * @see #setMethod(int)
- */
- public int getMethod() {
- return method;
- }
- /**
- * Sets the optional extra field data for the entry.
- * @param extra the extra field data bytes
- * @exception IllegalArgumentException if the length of the specified
- * extra field data is greater than 0xFFFF bytes
- * @see #getExtra()
- */
- public void setExtra(byte[] extra) {
- if (extra != null && extra.length > 0xFFFF) {
- throw new IllegalArgumentException("invalid extra field length");
- }
- this.extra = extra;
- }
- /**
- * Returns the extra field data for the entry, or null if none.
- * @return the extra field data for the entry, or null if none
- * @see #setExtra(byte[])
- */
- public byte[] getExtra() {
- return extra;
- }
- /**
- * Sets the optional comment string for the entry.
- * @param comment the comment string
- * @exception IllegalArgumentException if the length of the specified
- * comment string is greater than 0xFFFF bytes
- * @see #getComment()
- */
- public void setComment(String comment) {
- if (comment != null && comment.length() > 0xffff/3
- && ZipOutputStream.getUTF8Length(comment) > 0xffff) {
- throw new IllegalArgumentException("invalid entry comment length");
- }
- this.comment = comment;
- }
- /**
- * Returns the comment string for the entry, or null if none.
- * @return the comment string for the entry, or null if none
- * @see #setComment(String)
- */
- public String getComment() {
- return comment;
- }
- /**
- * Returns true if this is a directory entry. A directory entry is
- * defined to be one whose name ends with a '/'.
- * @return true if this is a directory entry
- */
- public boolean isDirectory() {
- return name.endsWith("/");
- }
- /**
- * Returns a string representation of the ZIP entry.
- */
- public String toString() {
- return getName();
- }
- /*
- * Converts DOS time to Java time (number of milliseconds since epoch).
- */
- private static long dosToJavaTime(long dtime) {
- Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
- (int)(((dtime >> 21) & 0x0f) - 1),
- (int)((dtime >> 16) & 0x1f),
- (int)((dtime >> 11) & 0x1f),
- (int)((dtime >> 5) & 0x3f),
- (int)((dtime << 1) & 0x3e));
- return d.getTime();
- }
- /*
- * Converts Java time to DOS time.
- */
- private static long javaToDosTime(long time) {
- Date d = new Date(time);
- int year = d.getYear() + 1900;
- if (year < 1980) {
- return (1 << 21) | (1 << 16);
- }
- return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
- d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
- d.getSeconds() >> 1;
- }
- /**
- * Returns the hash code value for this entry.
- */
- public int hashCode() {
- return name.hashCode();
- }
- /**
- * Returns a copy of this entry.
- */
- public Object clone() {
- try {
- ZipEntry e = (ZipEntry)super.clone();
- e.extra = (extra == null ? null : (byte[])extra.clone());
- return e;
- } catch (CloneNotSupportedException e) {
- // This should never happen, since we are Cloneable
- throw new InternalError();
- }
- }
- }
6. 在包中新建ZipInputStream类,代码如下:
ZipInputStream.java:
- package cn.edu.xdian.crytoll;
- import java.io.EOFException;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.PushbackInputStream;
- import java.io.UnsupportedEncodingException;
- import java.util.zip.CRC32;
- import java.util.zip.Inflater;
- import java.util.zip.ZipException;
- /**
- * This class implements an input stream filter for reading files in the
- * ZIP file format. Includes support for both compressed and uncompressed
- * entries.
- *
- * @author David Connelly
- * @version 1.44, 06/15/07
- */
- public
- class ZipInputStream extends InflaterInputStream implements ZipConstants {
- private ZipEntry entry;
- private int flag;
- private CRC32 crc = new CRC32();
- private long remaining;
- private byte[] tmpbuf = new byte[512];
- private static final int STORED = ZipEntry.STORED;
- private static final int DEFLATED = ZipEntry.DEFLATED;
- private boolean closed = false;
- // this flag is set to true after EOF has reached for
- // one entry
- private boolean entryEOF = false;
- /**
- * Check to make sure that this stream has not been closed
- */
- private void ensureOpen() throws IOException {
- if (closed) {
- throw new IOException("Stream closed");
- }
- }
- /**
- * Creates a new ZIP input stream.
- * @param in the actual input stream
- */
- public ZipInputStream(InputStream in) {
- super(new PushbackInputStream(in, 512), new Inflater(true), 512);
- usesDefaultInflater = true;
- if(in == null) {
- throw new NullPointerException("in is null");
- }
- }
- /**
- * Reads the next ZIP file entry and positions the stream at the
- * beginning of the entry data.
- * @return the next ZIP file entry, or null if there are no more entries
- * @exception ZipException if a ZIP file error has occurred
- * @exception IOException if an I/O error has occurred
- */
- public ZipEntry getNextEntry() throws IOException {
- ensureOpen();
- if (entry != null) {
- closeEntry();
- }
- crc.reset();
- inf.reset();
- if ((entry = readLOC()) == null) {
- return null;
- }
- if (entry.method == STORED) {
- remaining = entry.size;
- }
- entryEOF = false;
- return entry;
- }
- /**
- * Closes the current ZIP entry and positions the stream for reading the
- * next entry.
- * @exception ZipException if a ZIP file error has occurred
- * @exception IOException if an I/O error has occurred
- */
- public void closeEntry() throws IOException {
- ensureOpen();
- while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
- entryEOF = true;
- }
- /**
- * Returns 0 after EOF has reached for the current entry data,
- * otherwise always return 1.
- * <p>
- * Programs should not count on this method to return the actual number
- * of bytes that could be read without blocking.
- *
- * @return 1 before EOF and 0 after EOF has reached for current entry.
- * @exception IOException if an I/O error occurs.
- *
- */
- public int available() throws IOException {
- ensureOpen();
- if (entryEOF) {
- return 0;
- } else {
- return 1;
- }
- }
- /**
- * Reads from the current ZIP entry into an array of bytes.
- * If <code>len</code> is not zero, the method
- * blocks until some input is available; otherwise, no
- * bytes are read and <code>0</code> is returned.
- * @param b the buffer into which the data is read
- * @param off the start offset in the destination array <code>b</code>
- * @param len the maximum number of bytes read
- * @return the actual number of bytes read, or -1 if the end of the
- * entry is reached
- * @exception NullPointerException If <code>b</code> is <code>null</code>.
- * @exception IndexOutOfBoundsException If <code>off</code> is negative,
- * <code>len</code> is negative, or <code>len</code> is greater than
- * <code>b.length - off</code>
- * @exception ZipException if a ZIP file error has occurred
- * @exception IOException if an I/O error has occurred
- */
- public int read(byte[] b, int off, int len) throws IOException {
- ensureOpen();
- if (off < 0 || len < 0 || off > b.length - len) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return 0;
- }
- if (entry == null) {
- return -1;
- }
- switch (entry.method) {
- case DEFLATED:
- len = super.read(b, off, len);
- if (len == -1) {
- readEnd(entry);
- entryEOF = true;
- entry = null;
- } else {
- crc.update(b, off, len);
- }
- return len;
- case STORED:
- if (remaining <= 0) {
- entryEOF = true;
- entry = null;
- return -1;
- }
- if (len > remaining) {
- len = (int)remaining;
- }
- len = in.read(b, off, len);
- if (len == -1) {
- throw new ZipException("unexpected EOF");
- }
- crc.update(b, off, len);
- remaining -= len;
- if (remaining == 0 && entry.crc != crc.getValue()) {
- throw new ZipException(
- "invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) +
- " but got 0x" + Long.toHexString(crc.getValue()) + ")");
- }
- return len;
- default:
- throw new ZipException("invalid compression method");
- }
- }
- /**
- * Skips specified number of bytes in the current ZIP entry.
- * @param n the number of bytes to skip
- * @return the actual number of bytes skipped
- * @exception ZipException if a ZIP file error has occurred
- * @exception IOException if an I/O error has occurred
- * @exception IllegalArgumentException if n < 0
- */
- public long skip(long n) throws IOException {
- if (n < 0) {
- throw new IllegalArgumentException("negative skip length");
- }
- ensureOpen();
- int max = (int)Math.min(n, Integer.MAX_VALUE);
- int total = 0;
- while (total < max) {
- int len = max - total;
- if (len > tmpbuf.length) {
- len = tmpbuf.length;
- }
- len = read(tmpbuf, 0, len);
- if (len == -1) {
- entryEOF = true;
- break;
- }
- total += len;
- }
- return total;
- }
- /**
- * Closes this input stream and releases any system resources associated
- * with the stream.
- * @exception IOException if an I/O error has occurred
- */
- public void close() throws IOException {
- if (!closed) {
- super.close();
- closed = true;
- }
- }
- private byte[] b = new byte[256];
- /*
- * Reads local file (LOC) header for next entry.
- */
- private ZipEntry readLOC() throws IOException {
- try {
- readFully(tmpbuf, 0, LOCHDR);
- } catch (EOFException e) {
- return null;
- }
- if (get32(tmpbuf, 0) != LOCSIG) {
- return null;
- }
- // get the entry name and create the ZipEntry first
- int len = get16(tmpbuf, LOCNAM);
- int blen = b.length;
- if (len > blen) {
- do
- blen = blen * 2;
- while (len > blen);
- b = new byte[blen];
- }
- readFully(b, 0, len);
- ZipEntry e = createZipEntry(getUTF8String(b, 0, len));
- // now get the remaining fields for the entry
- flag = get16(tmpbuf, LOCFLG);
- if ((flag & 1) == 1) {
- throw new ZipException("encrypted ZIP entry not supported");
- }
- e.method = get16(tmpbuf, LOCHOW);
- e.time = get32(tmpbuf, LOCTIM);
- if ((flag & 8) == 8) {
- /* "Data Descriptor" present */
- if (e.method != DEFLATED) {
- throw new ZipException(
- "only DEFLATED entries can have EXT descriptor");
- }
- } else {
- e.crc = get32(tmpbuf, LOCCRC);
- e.csize = get32(tmpbuf, LOCSIZ);
- e.size = get32(tmpbuf, LOCLEN);
- }
- len = get16(tmpbuf, LOCEXT);
- if (len > 0) {
- byte[] bb = new byte[len];
- readFully(bb, 0, len);
- e.setExtra(bb);
- }
- return e;
- }
- /*
- * Fetches a UTF8-encoded String from the specified byte array.
- */
- private static String getUTF8String(byte[] b, int off, int len)
- {
- try
- {
- String s = new String(b, off, len, "GBK");
- return s;
- }
- catch (UnsupportedEncodingException e)
- {
- e.printStackTrace();
- }
- //以上为新添加的解决GBK乱码的
- // First, count the number of characters in the sequence
- int count = 0;
- int max = off + len;
- int i = off;
- while (i < max)
- {
- int c = b[i++] & 0xff;
- switch (c >> 4)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- // 0xxxxxxx
- count++;
- break;
- case 12:
- case 13:
- // 110xxxxx 10xxxxxx
- if ((int) (b[i++] & 0xc0) != 0x80)
- {
- throw new IllegalArgumentException();
- }
- count++;
- break;
- case 14:
- // 1110xxxx 10xxxxxx 10xxxxxx
- if (((int) (b[i++] & 0xc0) != 0x80)
- || ((int) (b[i++] & 0xc0) != 0x80))
- {
- throw new IllegalArgumentException();
- }
- count++;
- break;
- default:
- // 10xxxxxx, 1111xxxx
- throw new IllegalArgumentException();
- }
- }
- if (i != max)
- {
- throw new IllegalArgumentException();
- }
- // Now decode the characters...
- char[] cs = new char[count];
- i = 0;
- while (off < max)
- {
- int c = b[off++] & 0xff;
- switch (c >> 4)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- // 0xxxxxxx
- cs[i++] = (char) c;
- break;
- case 12:
- case 13:
- // 110xxxxx 10xxxxxx
- cs[i++] = (char) (((c & 0x1f) << 6) | (b[off++] & 0x3f));
- break;
- case 14:
- // 1110xxxx 10xxxxxx 10xxxxxx
- int t = (b[off++] & 0x3f) << 6;
- cs[i++] = (char) (((c & 0x0f) << 12) | t | (b[off++] & 0x3f));
- break;
- default:
- // 10xxxxxx, 1111xxxx
- throw new IllegalArgumentException();
- }
- }
- return new String(cs, 0, count);
- }
- /**
- * Creates a new <code>ZipEntry</code> object for the specified
- * entry name.
- *
- * @param name the ZIP file entry name
- * @return the ZipEntry just created
- */
- protected ZipEntry createZipEntry(String name) {
- return new ZipEntry(name);
- }
- /*
- * Reads end of deflated entry as well as EXT descriptor if present.
- */
- private void readEnd(ZipEntry e) throws IOException {
- int n = inf.getRemaining();
- if (n > 0) {
- ((PushbackInputStream)in).unread(buf, len - n, n);
- }
- if ((flag & 8) == 8) {
- /* "Data Descriptor" present */
- readFully(tmpbuf, 0, EXTHDR);
- long sig = get32(tmpbuf, 0);
- if (sig != EXTSIG) { // no EXTSIG present
- e.crc = sig;
- e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
- e.size = get32(tmpbuf, EXTLEN - EXTCRC);
- ((PushbackInputStream)in).unread(
- tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
- } else {
- e.crc = get32(tmpbuf, EXTCRC);
- e.csize = get32(tmpbuf, EXTSIZ);
- e.size = get32(tmpbuf, EXTLEN);
- }
- }
- if (e.size != inf.getBytesWritten()) {
- throw new ZipException(
- "invalid entry size (expected " + e.size +
- " but got " + inf.getBytesWritten() + " bytes)");
- }
- if (e.csize != inf.getBytesRead()) {
- throw new ZipException(
- "invalid entry compressed size (expected " + e.csize +
- " but got " + inf.getBytesRead() + " bytes)");
- }
- if (e.crc != crc.getValue()) {
- throw new ZipException(
- "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) +
- " but got 0x" + Long.toHexString(crc.getValue()) + ")");
- }
- }
- /*
- * Reads bytes, blocking until all bytes are read.
- */
- private void readFully(byte[] b, int off, int len) throws IOException {
- while (len > 0) {
- int n = in.read(b, off, len);
- if (n == -1) {
- throw new EOFException();
- }
- off += n;
- len -= n;
- }
- }
- /*
- * Fetches unsigned 16-bit value from byte array at specified offset.
- * The bytes are assumed to be in Intel (little-endian) byte order.
- */
- private static final int get16(byte b[], int off) {
- return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
- }
- /*
- * Fetches unsigned 32-bit value from byte array at specified offset.
- * The bytes are assumed to be in Intel (little-endian) byte order.
- */
- private static final long get32(byte b[], int off) {
- return get16(b, off) | ((long)get16(b, off+2) << 16);
- }
- }
7. 在包中新建ZipOutputStream类,代码如下:
ZipOutputStream.java:
- package cn.edu.xdian.crytoll;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.util.HashSet;
- import java.util.Vector;
- import java.util.zip.CRC32;
- import java.util.zip.Deflater;
- import java.util.zip.ZipException;
- /**
- * This class implements an output stream filter for writing files in the
- * ZIP file format. Includes support for both compressed and uncompressed
- * entries.
- *
- * @author David Connelly
- * @version 1.35, 07/31/06
- */
- public
- class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
- private static class XEntry {
- public final ZipEntry entry;
- public final long offset;
- public final int flag;
- public XEntry(ZipEntry entry, long offset) {
- this.entry = entry;
- this.offset = offset;
- this.flag = (entry.method == DEFLATED &&
- (entry.size == -1 ||
- entry.csize == -1 ||
- entry.crc == -1))
- // store size, compressed size, and crc-32 in data descriptor
- // immediately following the compressed entry data
- ? 8
- // store size, compressed size, and crc-32 in LOC header
- : 0;
- }
- }
- private XEntry current;
- private Vector<XEntry> xentries = new Vector<XEntry>();
- private HashSet<String> names = new HashSet<String>();
- private CRC32 crc = new CRC32();
- private long written = 0;
- private long locoff = 0;
- private String comment;
- private int method = DEFLATED;
- private boolean finished;
- private boolean closed = false;
- private static int version(ZipEntry e) throws ZipException {
- switch (e.method) {
- case DEFLATED: return 20;
- case STORED: return 10;
- default: throw new ZipException("unsupported compression method");
- }
- }
- /**
- * Checks to make sure that this stream has not been closed.
- */
- private void ensureOpen() throws IOException {
- if (closed) {
- throw new IOException("Stream closed");
- }
- }
- /**
- * Compression method for uncompressed (STORED) entries.
- */
- public static final int STORED = ZipEntry.STORED;
- /**
- * Compression method for compressed (DEFLATED) entries.
- */
- public static final int DEFLATED = ZipEntry.DEFLATED;
- /**
- * Creates a new ZIP output stream.
- * @param out the actual output stream
- */
- public ZipOutputStream(OutputStream out) {
- super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
- usesDefaultDeflater = true;
- }
- /**
- * Sets the ZIP file comment.
- * @param comment the comment string
- * @exception IllegalArgumentException if the length of the specified
- * ZIP file comment is greater than 0xFFFF bytes
- */
- public void setComment(String comment) {
- if (comment != null && comment.length() > 0xffff/3
- && getUTF8Length(comment) > 0xffff) {
- throw new IllegalArgumentException("ZIP file comment too long.");
- }
- this.comment = comment;
- }
- /**
- * Sets the default compression method for subsequent entries. This
- * default will be used whenever the compression method is not specified
- * for an individual ZIP file entry, and is initially set to DEFLATED.
- * @param method the default compression method
- * @exception IllegalArgumentException if the specified compression method
- * is invalid
- */
- public void setMethod(int method) {
- if (method != DEFLATED && method != STORED) {
- throw new IllegalArgumentException("invalid compression method");
- }
- this.method = method;
- }
- /**
- * Sets the compression level for subsequent entries which are DEFLATED.
- * The default setting is DEFAULT_COMPRESSION.
- * @param level the compression level (0-9)
- * @exception IllegalArgumentException if the compression level is invalid
- */
- public void setLevel(int level) {
- def.setLevel(level);
- }
- /**
- * Begins writing a new ZIP file entry and positions the stream to the
- * start of the entry data. Closes the current entry if still active.
- * The default compression method will be used if no compression method
- * was specified for the entry, and the current time will be used if
- * the entry has no set modification time.
- * @param e the ZIP entry to be written
- * @exception ZipException if a ZIP format error has occurred
- * @exception IOException if an I/O error has occurred
- */
- public void putNextEntry(ZipEntry e) throws IOException {
- ensureOpen();
- if (current != null) {
- closeEntry(); // close previous entry
- }
- if (e.time == -1) {
- e.setTime(System.currentTimeMillis());
- }
- if (e.method == -1) {
- e.method = method; // use default method
- }
- switch (e.method) {
- case DEFLATED:
- break;
- case STORED:
- // compressed size, uncompressed size, and crc-32 must all be
- // set for entries using STORED compression method
- if (e.size == -1) {
- e.size = e.csize;
- } else if (e.csize == -1) {
- e.csize = e.size;
- } else if (e.size != e.csize) {
- throw new ZipException(
- "STORED entry where compressed != uncompressed size");
- }
- if (e.size == -1 || e.crc == -1) {
- throw new ZipException(
- "STORED entry missing size, compressed size, or crc-32");
- }
- break;
- default:
- throw new ZipException("unsupported compression method");
- }
- if (! names.add(e.name)) {
- throw new ZipException("duplicate entry: " + e.name);
- }
- current = new XEntry(e, written);
- xentries.add(current);
- writeLOC(current);
- }
- /**
- * Closes the current ZIP entry and positions the stream for writing
- * the next entry.
- * @exception ZipException if a ZIP format error has occurred
- * @exception IOException if an I/O error has occurred
- */
- public void closeEntry() throws IOException {
- ensureOpen();
- if (current != null) {
- ZipEntry e = current.entry;
- switch (e.method) {
- case DEFLATED:
- def.finish();
- while (!def.finished()) {
- deflate();
- }
- if ((current.flag & 8) == 0) {
- // verify size, compressed size, and crc-32 settings
- if (e.size != def.getBytesRead()) {
- throw new ZipException(
- "invalid entry size (expected " + e.size +
- " but got " + def.getBytesRead() + " bytes)");
- }
- if (e.csize != def.getBytesWritten()) {
- throw new ZipException(
- "invalid entry compressed size (expected " +
- e.csize + " but got " + def.getBytesWritten() + " bytes)");
- }
- if (e.crc != crc.getValue()) {
- throw new ZipException(
- "invalid entry CRC-32 (expected 0x" +
- Long.toHexString(e.crc) + " but got 0x" +
- Long.toHexString(crc.getValue()) + ")");
- }
- } else {
- e.size = def.getBytesRead();
- e.csize = def.getBytesWritten();
- e.crc = crc.getValue();
- writeEXT(e);
- }
- def.reset();
- written += e.csize;
- break;
- case STORED:
- // we already know that both e.size and e.csize are the same
- if (e.size != written - locoff) {
- throw new ZipException(
- "invalid entry size (expected " + e.size +
- " but got " + (written - locoff) + " bytes)");
- }
- if (e.crc != crc.getValue()) {
- throw new ZipException(
- "invalid entry crc-32 (expected 0x" +
- Long.toHexString(e.crc) + " but got 0x" +
- Long.toHexString(crc.getValue()) + ")");
- }
- break;
- default:
- throw new ZipException("invalid compression method");
- }
- crc.reset();
- current = null;
- }
- }
- /**
- * Writes an array of bytes to the current ZIP entry data. This method
- * will block until all the bytes are written.
- * @param b the data to be written
- * @param off the start offset in the data
- * @param len the number of bytes that are written
- * @exception ZipException if a ZIP file error has occurred
- * @exception IOException if an I/O error has occurred
- */
- public synchronized void write(byte[] b, int off, int len)
- throws IOException
- {
- ensureOpen();
- if (off < 0 || len < 0 || off > b.length - len) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return;
- }
- if (current == null) {
- throw new ZipException("no current ZIP entry");
- }
- ZipEntry entry = current.entry;
- switch (entry.method) {
- case DEFLATED:
- super.write(b, off, len);
- break;
- case STORED:
- written += len;
- if (written - locoff > entry.size) {
- throw new ZipException(
- "attempt to write past end of STORED entry");
- }
- out.write(b, off, len);
- break;
- default:
- throw new ZipException("invalid compression method");
- }
- crc.update(b, off, len);
- }
- /**
- * Finishes writing the contents of the ZIP output stream without closing
- * the underlying stream. Use this method when applying multiple filters
- * in succession to the same output stream.
- * @exception ZipException if a ZIP file error has occurred
- * @exception IOException if an I/O exception has occurred
- */
- public void finish() throws IOException {
- ensureOpen();
- if (finished) {
- return;
- }
- if (current != null) {
- closeEntry();
- }
- if (xentries.size() < 1) {
- throw new ZipException("ZIP file must have at least one entry");
- }
- // write central directory
- long off = written;
- for (XEntry xentry : xentries)
- writeCEN(xentry);
- writeEND(off, written - off);
- finished = true;
- }
- /**
- * Closes the ZIP output stream as well as the stream being filtered.
- * @exception ZipException if a ZIP file error has occurred
- * @exception IOException if an I/O error has occurred
- */
- public void close() throws IOException {
- if (!closed) {
- super.close();
- closed = true;
- }
- }
- /*
- * Writes local file (LOC) header for specified entry.
- */
- private void writeLOC(XEntry xentry) throws IOException {
- ZipEntry e = xentry.entry;
- int flag = xentry.flag;
- writeInt(LOCSIG); // LOC header signature
- writeShort(version(e)); // version needed to extract
- writeShort(flag); // general purpose bit flag
- writeShort(e.method); // compression method
- writeInt(e.time); // last modification time
- if ((flag & 8) == 8) {
- // store size, uncompressed size, and crc-32 in data descriptor
- // immediately following compressed entry data
- writeInt(0);
- writeInt(0);
- writeInt(0);
- } else {
- writeInt(e.crc); // crc-32
- writeInt(e.csize); // compressed size
- writeInt(e.size); // uncompressed size
- }
- byte[] nameBytes = getUTF8Bytes(e.name);
- writeShort(nameBytes.length);
- writeShort(e.extra != null ? e.extra.length : 0);
- writeBytes(nameBytes, 0, nameBytes.length);
- if (e.extra != null) {
- writeBytes(e.extra, 0, e.extra.length);
- }
- locoff = written;
- }
- /*
- * Writes extra data descriptor (EXT) for specified entry.
- */
- private void writeEXT(ZipEntry e) throws IOException {
- writeInt(EXTSIG); // EXT header signature
- writeInt(e.crc); // crc-32
- writeInt(e.csize); // compressed size
- writeInt(e.size); // uncompressed size
- }
- /*
- * Write central directory (CEN) header for specified entry.
- * REMIND: add support for file attributes
- */
- private void writeCEN(XEntry xentry) throws IOException {
- ZipEntry e = xentry.entry;
- int flag = xentry.flag;
- int version = version(e);
- writeInt(CENSIG); // CEN header signature
- writeShort(version); // version made by
- writeShort(version); // version needed to extract
- writeShort(flag); // general purpose bit flag
- writeShort(e.method); // compression method
- writeInt(e.time); // last modification time
- writeInt(e.crc); // crc-32
- writeInt(e.csize); // compressed size
- writeInt(e.size); // uncompressed size
- byte[] nameBytes = getUTF8Bytes(e.name);
- writeShort(nameBytes.length);
- writeShort(e.extra != null ? e.extra.length : 0);
- byte[] commentBytes;
- if (e.comment != null) {
- commentBytes = getUTF8Bytes(e.comment);
- writeShort(commentBytes.length);
- } else {
- commentBytes = null;
- writeShort(0);
- }
- writeShort(0); // starting disk number
- writeShort(0); // internal file attributes (unused)
- writeInt(0); // external file attributes (unused)
- writeInt(xentry.offset); // relative offset of local header
- writeBytes(nameBytes, 0, nameBytes.length);
- if (e.extra != null) {
- writeBytes(e.extra, 0, e.extra.length);
- }
- if (commentBytes != null) {
- writeBytes(commentBytes, 0, commentBytes.length);
- }
- }
- /*
- * Writes end of central directory (END) header.
- */
- private void writeEND(long off, long len) throws IOException {
- int count = xentries.size();
- writeInt(ENDSIG); // END record signature
- writeShort(0); // number of this disk
- writeShort(0); // central directory start disk
- writeShort(count); // number of directory entries on disk
- writeShort(count); // total number of directory entries
- writeInt(len); // length of central directory
- writeInt(off); // offset of central directory
- if (comment != null) { // zip file comment
- byte[] b = getUTF8Bytes(comment);
- writeShort(b.length);
- writeBytes(b, 0, b.length);
- } else {
- writeShort(0);
- }
- }
- /*
- * Writes a 16-bit short to the output stream in little-endian byte order.
- */
- private void writeShort(int v) throws IOException {
- OutputStream out = this.out;
- out.write((v >>> 0) & 0xff);
- out.write((v >>> 8) & 0xff);
- written += 2;
- }
- /*
- * Writes a 32-bit int to the output stream in little-endian byte order.
- */
- private void writeInt(long v) throws IOException {
- OutputStream out = this.out;
- out.write((int)((v >>> 0) & 0xff));
- out.write((int)((v >>> 8) & 0xff));
- out.write((int)((v >>> 16) & 0xff));
- out.write((int)((v >>> 24) & 0xff));
- written += 4;
- }
- /*
- * Writes an array of bytes to the output stream.
- */
- private void writeBytes(byte[] b, int off, int len) throws IOException {
- super.out.write(b, off, len);
- written += len;
- }
- /*
- * Returns the length of String's UTF8 encoding.
- */
- static int getUTF8Length(String s) {
- int count = 0;
- for (int i = 0; i < s.length(); i++) {
- char ch = s.charAt(i);
- if (ch <= 0x7f) {
- count++;
- } else if (ch <= 0x7ff) {
- count += 2;
- } else {
- count += 3;
- }
- }
- return count;
- }
- /*
- * Returns an array of bytes representing the UTF8 encoding
- * of the specified String.
- */
- private static byte[] getUTF8Bytes(String s) {
- char[] c = s.toCharArray();
- int len = c.length;
- // Count the number of encoded bytes...
- int count = 0;
- for (int i = 0; i < len; i++) {
- int ch = c[i];
- if (ch <= 0x7f) {
- count++;
- } else if (ch <= 0x7ff) {
- count += 2;
- } else {
- count += 3;
- }
- }
- // Now return the encoded bytes...
- byte[] b = new byte[count];
- int off = 0;
- for (int i = 0; i < len; i++) {
- int ch = c[i];
- if (ch <= 0x7f) {
- b[off++] = (byte)ch;
- } else if (ch <= 0x7ff) {
- b[off++] = (byte)((ch >> 6) | 0xc0);
- b[off++] = (byte)((ch & 0x3f) | 0x80);
- } else {
- b[off++] = (byte)((ch >> 12) | 0xe0);
- b[off++] = (byte)(((ch >> 6) & 0x3f) | 0x80);
- b[off++] = (byte)((ch & 0x3f) | 0x80);
- }
- }
- return b;
- }
- }
8. 新建一个Application Window,代码如下:
package cn.edu.xdian.crytoll;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel; import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; import cn.edu.xdian.crytoll.ZipEntry;
import cn.edu.xdian.crytoll.ZipInputStream;
import cn.edu.xdian.crytoll.ZipOutputStream; /**
* 获取文件列表的过滤器
*
* @author 李钟尉
*/
public class UnZipTextFileFrame extends JFrame {
private JPanel contentPane;
private JTextField forderField;
private JTextField templetField;
private File file;
private File dir;
private JTable table;
private JTextField extNameField;
private JSpinner startSpinner;
private JTextField textField;
private JTextField textField_1;
private DefaultTableModel model;
private String filesrc;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UnZipTextFileFrame frame = new UnZipTextFileFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
} /**
* Create the frame.
*/
public UnZipTextFileFrame() {
setResizable(false);
setTitle("压缩包解压到指定文件夹");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 500, 300);
getContentPane().setLayout(null); textField = new JTextField();
textField.setBounds(10, 10, 158, 21);
getContentPane().add(textField);
textField.setColumns(10); JButton btnZip = new JButton("Zip\u6587\u4EF6");
btnZip.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
do_btnZip_actionPerformed(e);
}
});
btnZip.setBounds(178, 9, 93, 23);
getContentPane().add(btnZip); textField_1 = new JTextField();
textField_1.setBounds(281, 10, 100, 21);
getContentPane().add(textField_1);
textField_1.setColumns(10); JButton btnNewButton = new JButton("解压到");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
do_btnNewButton_actionPerformed(e);
}
});
btnNewButton.setBounds(391, 9, 93, 23);
getContentPane().add(btnNewButton); JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 41, 474, 170);
getContentPane().add(scrollPane); table = new JTable();
scrollPane.setViewportView(table);
model= (DefaultTableModel) table.getModel();
model.setColumnIdentifiers(new Object[] { "序号", "文件名"});
JButton button = new JButton("\u5F00\u59CB\u89E3\u538B\u7F29");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
do_button_actionPerformed(e);
}
});
button.setBounds(178, 221, 100, 23);
getContentPane().add(button); }
protected void do_btnZip_actionPerformed(ActionEvent e){
JFileChooser chooser = new JFileChooser();// 创建文件选择器
int option = chooser.showOpenDialog(this);// 显示文件打开对话框
if (option == JFileChooser.APPROVE_OPTION) {
file = chooser.getSelectedFile();// 获取选择的文件数组
filesrc=file.getAbsolutePath();
textField.setText(filesrc);// 清空文本框
} else {
textField.setText("");// 清空文本框
}
}
protected void do_btnNewButton_actionPerformed(ActionEvent e){
JFileChooser chooser = new JFileChooser();// 创建文件选择器
// 设置选择器只针对文件夹生效
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int option = chooser.showOpenDialog(this);// 显示文件打开对话框
if (option == JFileChooser.APPROVE_OPTION) {
dir = chooser.getSelectedFile();// 获取选择的文件夹
textField_1.setText(dir.toString());// 显示文件夹到文本框
} else {
dir = null;
textField_1.setText("");
}
}
protected void do_button_actionPerformed(ActionEvent e){
ZipInputStream zin;
try{
//filesrc=new String(filesrc.getBytes("ISO-8859-1"),"UTF-8");
FileInputStream in = new FileInputStream(filesrc);
zin=new ZipInputStream(in);
ZipEntry entry;
int i=1;
while(((entry=zin.getNextEntry())!=null)&&!entry.isDirectory()){
File file=new File(dir.toString()+"/"+entry.getName());
if(!file.exists()){
file.createNewFile();
}
zin.closeEntry();
Object[] property = new Object[2];
property[0] = i;
property[1] = entry.getName();
model.addRow(property);
i++;
}
}catch(Exception ex){
ex.printStackTrace();
}
}
}
效果如图:
Java压缩包解压到指定文件的更多相关文章
- 把自解压的RAR压缩包解压到指定的软件安装目录
原文 把自解压的RAR压缩包解压到指定的软件安装目录 今天千里独行同学给轻狂来信问了一个问题:如何把一个自解压的RAR压缩包解压到我们指定的软件安装目录. 其实,在NSIS中,我们可以灵活运用相关 ...
- 用tar命令把目标压缩包解压到指定位置
linux下tar命令解压到指定的目录 : #tar zxvf /bbs.tar.zip -C /zzz/bbs //把根目录下的bbs.tar.zip解压到/zzz/bbs下,前提要保证存在/ ...
- zend framework将zip格式的压缩文件导入并解压到指定文件
html代码 <pre class="php" name="code"><fieldset> <legend>批量导入学生照 ...
- java 提取(解压)zip文件中特定后缀的文件并保存到指定目录
内容简介 本文主要介绍使用ZipFile来提取zip压缩文件中特定后缀(如:png,jpg)的文件并保存到指定目录下. 导入包:import java.util.zip.ZipFile; 如需添加对r ...
- Java实现zip文件解压[到指定目录]
2019独角兽企业重金招聘Python工程师标准>>> package com.ljheee.ziptool.core; import java.io.File; import ja ...
- java 提取(解压)rar文件中特定后缀的文件并保存到指定目录
内容简介 本文主要介绍使用junrar来提取rar压缩文件中特定后缀(如:png,jpg)的文件并保存到指定目录下. 支持v4及以下版本压缩文件,不支持v5及以上. 在rar文件上右键,查看属性,在压 ...
- 《OD学hadoop》在LINUX下如何将tar压缩文件解压到指定的目录下
linux下tar命令解压到指定的目录 :#tar zxvf /bbs.tar.zip -C /zzz/bbs //把根目录下的bbs.tar.zip解压到/zzz/bbs下,前提要保证存在/zzz/ ...
- Java动态解压zip压缩包
import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; impo ...
- tar 解压某个指定的文件或者文件夹
1. 先查看压缩文档中有那些文件,如果都不清楚文件内容,然后就直接解压,这个是不可能的 使用#tar -tf 压缩包名称,可以查看压缩包内容 2.解压某个文件 tar -zxvf zabbix.tar ...
随机推荐
- 解决EasyUi中的DataGrid删除一条记录后,被删除的数据仍处于被选中状态问题
项目中遇到这么一个问题,在easyui的datagrid中,删除一条记录成功,重新加载datagrid后,去点编辑操作,仍可把之前删除掉的那条记录进行编辑操作,正常情况应该是,删除后再去点击“编辑”, ...
- 基于octree的空间划分及搜索操作
(1) octree是一种用于管理稀疏3D数据的树形数据结构,每个内部节点都正好有八个子节点,介绍如何用octree在点云数据中进行空间划分及近邻搜索,实现“体素内近邻搜索(Neighbors wi ...
- Ubuntu下qemu环境搭建
在查找资料过程中,发现自己搭建虚拟的arm环境的话,有一个比较好的软件就是qemu了,当然还有其他的,大家各投所好就好. 接下来说一下qemu环境搭建过程. 其实搭建很简单,作为小白,我还是捣鼓了两三 ...
- js dom 创建table标签和子属性, 以及创建多选框
代码: <div class="Category"> <span id="Edit_headerTitle">Edit Categori ...
- Java如何处理异常层次结构?
在Java编程中,如何处理异常层次结构? 以下是异常层次结构的示例图 - 此示例显示如何通过扩展Exception类来处理异常层次结构. package com.yiibai; class Anima ...
- Mybatis表关联一对多
有了前面几章的基础,对一些简单的应用是可以处理的,但在实际项目中,经常是关联表的查询,比如:最常见到的多对一,一对多等.这些查询是如何处理的呢,这一讲就讲这个问题.前面几篇教程中介绍的都是单表映射的一 ...
- 于erlang依赖的linux调优
[皇室]杭州-sunface(61087682) 上午 9:42:02 http://docs.basho.com/riak/latest/ops/tuning/linux/ 这篇文章对于erlang ...
- 【转】Castle Windsor之组件注册
[转]Castle Windsor之组件注册 注册方式较多,大体有这么几种,学习得比较粗浅,先记录: 1.逐个注册组件 即对每个接口通过代码指定其实现类,代码: container.Register( ...
- Castle.Windsor依赖注入的高级应用_Castle.Windsor.3.1.0
[转]Castle.Windsor依赖注入的高级应用_Castle.Windsor.3.1.0 1. 使用代码方式进行组件注册[依赖服务类] using System; using System.Co ...
- C# 判断一个字符串是否为url
/// <summary> /// 判断一个字符串是否为url /// </summary> /// <param name="str">< ...