zip压缩(不是解压)在java里的用法,己解决中文问题。
首先上代码,一个是工具类,一个是修该的SUN RUNTIME 里的 ZipOutputStream 类(用来解决中文乱码问题)。
ZipTools.java
package
net.techjava.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.techjava.zip.ZipEntry;
import net.techjava.zip.ZipOutputStream;
public class ZipTools {
/**
* 生成ZIP文件,把一系列的文件生成到一个ZIP里,使用无目录的形式。
* @param fileFullPathList 要压缩的文件列表
* @param outputFullFileName 压缩成的文件的输出路径
* @author Beiling Yu 2008年10月27日 14时59分18秒
* @return
*/
public static boolean MakeZip(List < String > fileFullPathList,String outputFullFileName){
try {
byte [] buf = new byte [ 1024 ];
ZipOutputStream out = new ZipOutputStream( new FileOutputStream(outputFullFileName));
for (Iterator < String > i = fileFullPathList.iterator(); i.hasNext();) {
String nowFilePath = (String)i.next();
File nowFile = new File(nowFilePath);
FileInputStream in = new FileInputStream(nowFile);
// out.putNextEntry(new ZipEntry(new String(nowFile.getName().getBytes("gb2312"),"ISO8859-1")));
out.putNextEntry( new ZipEntry(nowFile.getName()));
int len;
while ((len = in.read(buf)) > 0 ) {
out.write(buf, 0 , len);
}
out.closeEntry();
in.close();
}
out.close();
} catch (Exception e) {
e.printStackTrace();
return false ;
}
return true ;
}
public static void main(String[] args) {
List < String > flist = new ArrayList < String > ();
flist.add( " D:\\中文1.doc " );
flist.add( " D:\\中文2.doc " );
flist.add( " D:\\中文3.doc " );
flist.add( " D:\\tet.doc " );
flist.add( " D:\\Tomcat5.doc " );
System.out.println(MakeZip(flist, " D:\\temp.zip " ));
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.techjava.zip.ZipEntry;
import net.techjava.zip.ZipOutputStream;
public class ZipTools {
/**
* 生成ZIP文件,把一系列的文件生成到一个ZIP里,使用无目录的形式。
* @param fileFullPathList 要压缩的文件列表
* @param outputFullFileName 压缩成的文件的输出路径
* @author Beiling Yu 2008年10月27日 14时59分18秒
* @return
*/
public static boolean MakeZip(List < String > fileFullPathList,String outputFullFileName){
try {
byte [] buf = new byte [ 1024 ];
ZipOutputStream out = new ZipOutputStream( new FileOutputStream(outputFullFileName));
for (Iterator < String > i = fileFullPathList.iterator(); i.hasNext();) {
String nowFilePath = (String)i.next();
File nowFile = new File(nowFilePath);
FileInputStream in = new FileInputStream(nowFile);
// out.putNextEntry(new ZipEntry(new String(nowFile.getName().getBytes("gb2312"),"ISO8859-1")));
out.putNextEntry( new ZipEntry(nowFile.getName()));
int len;
while ((len = in.read(buf)) > 0 ) {
out.write(buf, 0 , len);
}
out.closeEntry();
in.close();
}
out.close();
} catch (Exception e) {
e.printStackTrace();
return false ;
}
return true ;
}
public static void main(String[] args) {
List < String > flist = new ArrayList < String > ();
flist.add( " D:\\中文1.doc " );
flist.add( " D:\\中文2.doc " );
flist.add( " D:\\中文3.doc " );
flist.add( " D:\\tet.doc " );
flist.add( " D:\\Tomcat5.doc " );
System.out.println(MakeZip(flist, " D:\\temp.zip " ));
}
}
ZipOutputStream.java
/*
*
*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package net.techjava.zip;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.zip.CRC32;
import java.util.zip.Deflater;
import java.util.zip.ZipException;
public
class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
private ZipEntry entry;
private Vector entries = new Vector();
private Hashtable names = new Hashtable();
private CRC32 crc = new CRC32();
private long written;
private long locoff = 0 ;
private String comment;
private int method = DEFLATED;
private boolean finished;
private boolean closed = false ;
/**
* Check 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 (entry != 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:
if (e.size == - 1 || e.csize == - 1 || e.crc == - 1 ) {
// store size, compressed size, and crc-32 in data descriptor
// immediately following the compressed entry data
e.flag = 8 ;
} else if (e.size != - 1 && e.csize != - 1 && e.crc != - 1 ) {
// store size, compressed size, and crc-32 in LOC header
e.flag = 0 ;
} else {
throw new ZipException(
" DEFLATED entry missing size, compressed size, or crc-32 " );
}
e.version = 20 ;
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 " );
}
e.version = 10 ;
e.flag = 0 ;
break ;
default :
throw new ZipException( " unsupported compression method " );
}
e.offset = written;
if (names.put(e.name, e) != null ) {
throw new ZipException( " duplicate entry: " + e.name);
}
writeLOC(e);
entries.addElement(e);
entry = e;
}
/**
* 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();
ZipEntry e = entry;
if (e != null ) {
switch (e.method) {
case DEFLATED:
def.finish();
while ( ! def.finished()) {
deflate();
}
if ((e.flag & 8 ) == 0 ) {
// verify size, compressed size, and crc-32 settings
if (e.size != def.getTotalIn()) {
throw new ZipException(
" invalid entry size (expected " + e.size +
" but got " + def.getTotalIn() + " bytes) " );
}
if (e.csize != def.getTotalOut()) {
throw new ZipException(
" invalid entry compressed size (expected " +
e.csize + " but got " + def.getTotalOut() +
" 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.getTotalIn();
e.csize = def.getTotalOut();
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 InternalError( " invalid compression method " );
}
crc.reset();
entry = 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 (entry == null ) {
throw new ZipException( " no current ZIP 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 InternalError( " 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 (entry != null ) {
closeEntry();
}
if (entries.size() < 1 ) {
throw new ZipException( " ZIP file must have at least one entry " );
}
// write central directory
long off = written;
Enumeration e = entries.elements();
while (e.hasMoreElements()) {
writeCEN((ZipEntry)e.nextElement());
}
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(ZipEntry e) throws IOException {
writeInt(LOCSIG); // LOC header signature
writeShort(e.version); // version needed to extract
writeShort(e.flag); // general purpose bit flag
writeShort(e.method); // compression method
writeInt(e.time); // last modification time
if ((e.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(ZipEntry e) throws IOException {
writeInt(CENSIG); // CEN header signature
writeShort(e.version); // version made by
writeShort(e.version); // version needed to extract
writeShort(e.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(e.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 {
writeInt(ENDSIG); // END record signature
writeShort( 0 ); // number of this disk
writeShort( 0 ); // central directory start disk
writeShort(entries.size()); // number of directory entries on disk
writeShort(entries.size()); // 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;
try {
return s.getBytes( " gbk " );
} catch (UnsupportedEncodingException e) {
return getUTF8Bytes(s);
}
}
}
*
*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package net.techjava.zip;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.zip.CRC32;
import java.util.zip.Deflater;
import java.util.zip.ZipException;
public
class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
private ZipEntry entry;
private Vector entries = new Vector();
private Hashtable names = new Hashtable();
private CRC32 crc = new CRC32();
private long written;
private long locoff = 0 ;
private String comment;
private int method = DEFLATED;
private boolean finished;
private boolean closed = false ;
/**
* Check 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 (entry != 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:
if (e.size == - 1 || e.csize == - 1 || e.crc == - 1 ) {
// store size, compressed size, and crc-32 in data descriptor
// immediately following the compressed entry data
e.flag = 8 ;
} else if (e.size != - 1 && e.csize != - 1 && e.crc != - 1 ) {
// store size, compressed size, and crc-32 in LOC header
e.flag = 0 ;
} else {
throw new ZipException(
" DEFLATED entry missing size, compressed size, or crc-32 " );
}
e.version = 20 ;
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 " );
}
e.version = 10 ;
e.flag = 0 ;
break ;
default :
throw new ZipException( " unsupported compression method " );
}
e.offset = written;
if (names.put(e.name, e) != null ) {
throw new ZipException( " duplicate entry: " + e.name);
}
writeLOC(e);
entries.addElement(e);
entry = e;
}
/**
* 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();
ZipEntry e = entry;
if (e != null ) {
switch (e.method) {
case DEFLATED:
def.finish();
while ( ! def.finished()) {
deflate();
}
if ((e.flag & 8 ) == 0 ) {
// verify size, compressed size, and crc-32 settings
if (e.size != def.getTotalIn()) {
throw new ZipException(
" invalid entry size (expected " + e.size +
" but got " + def.getTotalIn() + " bytes) " );
}
if (e.csize != def.getTotalOut()) {
throw new ZipException(
" invalid entry compressed size (expected " +
e.csize + " but got " + def.getTotalOut() +
" 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.getTotalIn();
e.csize = def.getTotalOut();
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 InternalError( " invalid compression method " );
}
crc.reset();
entry = 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 (entry == null ) {
throw new ZipException( " no current ZIP 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 InternalError( " 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 (entry != null ) {
closeEntry();
}
if (entries.size() < 1 ) {
throw new ZipException( " ZIP file must have at least one entry " );
}
// write central directory
long off = written;
Enumeration e = entries.elements();
while (e.hasMoreElements()) {
writeCEN((ZipEntry)e.nextElement());
}
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(ZipEntry e) throws IOException {
writeInt(LOCSIG); // LOC header signature
writeShort(e.version); // version needed to extract
writeShort(e.flag); // general purpose bit flag
writeShort(e.method); // compression method
writeInt(e.time); // last modification time
if ((e.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(ZipEntry e) throws IOException {
writeInt(CENSIG); // CEN header signature
writeShort(e.version); // version made by
writeShort(e.version); // version needed to extract
writeShort(e.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(e.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 {
writeInt(ENDSIG); // END record signature
writeShort( 0 ); // number of this disk
writeShort( 0 ); // central directory start disk
writeShort(entries.size()); // number of directory entries on disk
writeShort(entries.size()); // 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;
try {
return s.getBytes( " gbk " );
} catch (UnsupportedEncodingException e) {
return getUTF8Bytes(s);
}
}
}
时间关系,大家自己看啊,其实就是改了最后一个函数( private static byte [] getUTF8Bytes(String s) )。