首页 / JAVA / Java压缩包解压到指定文件
Java压缩包解压到指定文件
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java压缩包解压到指定文件,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含55470字,纯文字阅读大概需要80分钟。
内容图文
在获得一个以<SPAN style=‘font-family: "Times New Roman";‘>Zip
格式压缩的文件之后,需要将其进行解压缩,还原成压缩前的文件。若是使用 "Times New Roman";‘>Java自带的压缩工具包来实现解压缩文件到指定文件夹的功能,因为jdk提供的"Times New Roman";‘>zip只能按"Times New Roman";‘>UTF-8格式处理,而"Times New Roman";‘>Windows系统中文件名是以"Times New Roman";‘>GBK方式编码的,所以如果是解压一个包含中文文件名的"Times New Roman";‘>zip包,会报非法参数异常,如图所示:
所以要实现解压缩,就得对<SPAN style=‘font-family: "Times New Roman";‘>DeflaterOutputStream.java、<SPAN style=‘font-family: "Times New Roman";‘>InflaterInputStream.java、<SPAN style=‘font-family: "Times New Roman";‘>ZipConstants.java、<SPAN style=‘font-family: "Times New Roman";‘>ZipEntry.java、<SPAN style=‘font-family: "Times New Roman";‘>ZipInputStream.java以及<SPAN style=‘font-family: "Times New Roman";‘>ZipOutputStream.java这些相关的类进行修改,过程如下:
- 因为从 J2SE 1.4 开始,Java 编译器不再支持 import 进未命包名的类、接口,所以在创建的Java项目中,一定要新建一个自己定义的包,包命名的格式一般为学校域名的逆序+自己的网名,比如cn.edu.xidian.crytoll。
- 在包内新建DeflaterOutputStream类,代码如下:
DeflaterOutputStream.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | 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. 在包内新建<SPAN style=‘font-family: "Times New Roman";‘>InflaterInputStream类,代码如下:
InflaterInputStream.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | 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. 在包中新建<SPAN style=‘font-family: "Times New Roman";‘>ZipConstants接口,代码如下:
ZipConstants.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 | 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,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | 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(); } } } |
效果如图:
原文:http://www.cnblogs.com/cysolo/p/3575466.html
内容总结
以上是互联网集市为您收集整理的Java压缩包解压到指定文件全部内容,希望文章能够帮你解决Java压缩包解压到指定文件所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。