Java压缩包解压到指定文件

欢迎进入Java社区论坛,与200万技术人员互动交流 >>进入

  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 ZipEntry object for the specified

  * entry name.

  *

  * @param name the ZIP file entry name

  * @return the ZipEntry just created

  */

  protected ZipEntry createZipEntry(String name) {

  return new ZipEntry(name);

  }

  /*

  * Reads end of deflated entry as well as EXT descriptor if present.

  */

  private void readEnd(ZipEntry e) throws IOException {

  int n = inf.getRemaining();

  if (n > 0) {

  ((PushbackInputStream)in).unread(buf, len – n, n);

  }

  if ((flag & 8) == 8) {

  /* “Data Descriptor” present */

  readFully(tmpbuf, 0, EXTHDR);

  long sig = get32(tmpbuf, 0);

  if (sig != EXTSIG) { // no EXTSIG present

  e.crc = sig;

  e.csize = get32(tmpbuf, EXTSIZ – EXTCRC);

  e.size = get32(tmpbuf, EXTLEN – EXTCRC);

  ((PushbackInputStream)in).unread(

  tmpbuf, EXTHDR – EXTCRC – 1, EXTCRC);

  } else {

  e.crc = get32(tmpbuf, EXTCRC);

  e.csize = get32(tmpbuf, EXTSIZ);

  e.size = get32(tmpbuf, EXTLEN);

  }

  }

  if (e.size != inf.getBytesWritten()) {

  throw new ZipException(

  ”invalid entry size (expected ” + e.size +

  ” but got ” + inf.getBytesWritten() + ” bytes)”);

  }

  if (e.csize != inf.getBytesRead()) {

  throw new ZipException(

  ”invalid entry compressed size (expected ” + e.csize +

  ” but got ” + inf.getBytesRead() + ” bytes)”);

  }

  if (e.crc != crc.getValue()) {

  throw new ZipException(

  ”invalid entry CRC (expected 0x” + Long.toHexString(e.crc) +

  ” but got 0x” + Long.toHexString(crc.getValue()) + “)”);

  }

  }

  /*

  * Reads bytes, blocking until all bytes are read.

  */

  private void readFully(byte[] b, int off, int len) throws IOException {

  while (len > 0) {

  int n = in.read(b, off, len);

  if (n == -1) {

  throw new EOFException();

  }

  off += n;

  len -= n;

  }

  }

  /*

  * Fetches unsigned 16-bit value from byte array at specified offset.

  * The bytes are assumed to be in Intel (little-endian) byte order.

  */

  private static final int get16(byte b[], int off) {

  return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);

  }

  /*

  * Fetches unsigned 32-bit value from byte array at specified offset.

  * The bytes are assumed to be in Intel (little-endian) byte order.

  */

  private static final long get32(byte b[], int off) {

  return get16(b, off) | ((long)get16(b, off+2) << 16);

  }

  }

  7. 在包中新建ZipOutputStream类,代码如下:

  ZipOutputStream.java:

  package cn.edu.xdian.crytoll;

  import java.io.IOException;

  import java.io.OutputStream;

  import java.util.HashSet;

  import java.util.Vector;

  import java.util.zip.CRC32;

  import java.util.zip.Deflater;

  import java.util.zip.ZipException;

  /**

  * This class implements an output stream filter for writing files in the

  * ZIP file format. Includes support for both compressed and uncompressed

  * entries.

  *

  * @author David Connelly

  * @version 1.35, 07/31/06

  */

  public

  class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {

  private static class XEntry {

  public final ZipEntry entry;

  public final long offset;

  public final int flag;

  public XEntry(ZipEntry entry, long offset) {

  this.entry = entry;

  this.offset = offset;

  this.flag = (entry.method == DEFLATED &&

  (entry.size == -1 ||

  entry.csize == -1 ||

  entry.crc == -1))

  // store size, compressed size, and crc-32 in data descriptor

  // immediately following the compressed entry data

  ? 8

  // store size, compressed size, and crc-32 in LOC header

  : 0;

  }

  }

  private XEntry current;

  private Vector xentries = new Vector();

  private HashSet names = new HashSet();

  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()) + “)”);

  }

[1][2][3][4]

明天是世上增值最快的一块土地,因它充满了希望

Java压缩包解压到指定文件

相关文章:

你感兴趣的文章:

标签云: