Methods Summary |
---|
public void | close()Closes the ZIP output stream as well as the stream being filtered.
if (!closed) {
super.close();
closed = true;
}
|
public void | closeEntry()Closes the current ZIP entry and positions the stream for writing
the next entry.
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;
}
|
private void | ensureOpen()Checks to make sure that this stream has not been closed.
if (closed) {
throw new IOException("Stream closed");
}
|
public void | finish()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.
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;
|
private static byte[] | getUTF8Bytes(java.lang.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;
|
static int | getUTF8Length(java.lang.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;
|
public void | putNextEntry(java.util.zip.ZipEntry e)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.
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);
|
public void | setComment(java.lang.String comment)Sets the ZIP file comment.
if (comment != null && comment.length() > 0xffff/3
&& getUTF8Length(comment) > 0xffff) {
throw new IllegalArgumentException("ZIP file comment too long.");
}
this.comment = comment;
|
public void | setLevel(int level)Sets the compression level for subsequent entries which are DEFLATED.
The default setting is DEFAULT_COMPRESSION.
def.setLevel(level);
|
public void | setMethod(int method)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.
if (method != DEFLATED && method != STORED) {
throw new IllegalArgumentException("invalid compression method");
}
this.method = method;
|
private static int | version(java.util.zip.ZipEntry e)
switch (e.method) {
case DEFLATED: return 20;
case STORED: return 10;
default: throw new ZipException("unsupported compression method");
}
|
public synchronized void | write(byte[] b, int off, int len)Writes an array of bytes to the current ZIP entry data. This method
will block until all the bytes are written.
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);
|
private void | writeBytes(byte[] b, int off, int len)
super.out.write(b, off, len);
written += len;
|
private void | writeCEN(java.util.zip.ZipOutputStream$XEntry xentry)
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);
}
|
private void | writeEND(long off, long len)
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);
}
|
private void | writeEXT(java.util.zip.ZipEntry e)
writeInt(EXTSIG); // EXT header signature
writeInt(e.crc); // crc-32
writeInt(e.csize); // compressed size
writeInt(e.size); // uncompressed size
|
private void | writeInt(long v)
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;
|
private void | writeLOC(java.util.zip.ZipOutputStream$XEntry xentry)
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;
|
private void | writeShort(int v)
OutputStream out = this.out;
out.write((v >>> 0) & 0xff);
out.write((v >>> 8) & 0xff);
written += 2;
|