随笔 - 8  文章 - 24  trackbacks - 0
<2008年10月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

常用链接

留言簿(4)

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

首先上代码,一个是工具类,一个是修该的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"));

        }

}

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);
        }
    }
}

时间关系,大家自己看啊,其实就是改了最后一个函数(  private static byte[] getUTF8Bytes(String s)  )。
posted on 2008-10-30 17:55 Vincent.Yu 阅读(12509) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: