czipoutputstream.java

来自「对eclipse gef进行封装,可以生成图形化编辑器」· Java 代码 · 共 536 行 · 第 1/2 页

JAVA
536
字号
/*******************************************************************************
 * $Header: /cvsroot/EOS6/work_dir/niegy/com.primeton.studio.gef.ui/src/com/primeton/studio/gef/ui/zip/CZipOutputStream.java,v 1.1 2007/01/23 06:35:15 niegy Exp $
 * $Revision: 1.1 $
 * $Date: 2007/01/23 06:35:15 $
 *
 *==============================================================================
 *
 * Copyright (c) 2001-2006 Primeton Technologies, Ltd.
 * All rights reserved.
 * 
 * Created on 2007-1-22
 *******************************************************************************/


package com.primeton.studio.gef.ui.zip;

import java.io.IOException;
import java.io.OutputStream;
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.DeflaterOutputStream;
import java.util.zip.ZipException;

/**
 * TODO 此处填写 class 信息
 *
 * @author niegy (mailto:niegy@primeton.com)
 */
/*
 * 修改历史
 * $Log: CZipOutputStream.java,v $
 * Revision 1.1  2007/01/23 06:35:15  niegy
 * 实现压缩功能,支持中文
 * 
 */
class CZipOutputStream extends DeflaterOutputStream implements CZipConstants {

	private String encoding="UTF-8"; 
	
	  private CZipEntry entry;
	    private Vector entries = new Vector();
	    private Hashtable names = new Hashtable();
	    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;
	    
	    /**
	     * 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 = CZipEntry.STORED;

	    /**
	     * Compression method for compressed (DEFLATED) entries.
	     */
	    public static final int DEFLATED = CZipEntry.DEFLATED;

	    /**
	     * Creates a new ZIP output stream.
	     * @param out the actual output stream
	     */
	    public CZipOutputStream(OutputStream out,String encoding) {
			super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
	//	        usesDefaultDeflater = true;
			this.encoding=encoding;
	    }

	    /**
	     * 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(CZipEntry 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();
		CZipEntry 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.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 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) {

⌨️ 快捷键说明

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