ZipOutputStream.java [plain text]
package java.util.zip;
import java.io.*;
public class ZipOutputStream extends DeflaterOutputStream
implements ZipConstants
{
public static final int STORED = 0;
public static final int DEFLATED = 8;
public void close () throws IOException
{
finish ();
out.close();
}
public void closeEntry () throws IOException
{
int compressed_size;
if (current.method == STORED)
{
compressed_size = uncompressed_size;
}
else
{
super.finish();
compressed_size = def.getTotalOut();
}
long crc = sum.getValue();
bytes_written += compressed_size;
if (current.getCrc() == -1 || current.getCompressedSize() == -1
|| current.getSize() == -1)
{
current.setCrc(crc);
current.compressedSize = compressed_size;
current.setSize(uncompressed_size);
put4 (0x08074b50);
put4 ((int) (current.getCrc()));
put4 ((int) (current.getCompressedSize()));
put4 ((int) (current.getSize()));
bytes_written += 16;
}
else if (current.getCrc() != crc
|| current.getCompressedSize() != compressed_size
|| current.getSize() != uncompressed_size)
throw new ZipException ("zip entry field incorrect");
current.next = chain;
chain = current;
current = null;
}
public void write (int bval) throws IOException
{
if (current.method == STORED)
{
out.write(bval);
}
else
super.write(bval);
sum.update(bval);
uncompressed_size += 1;
}
public void write (byte[] buf, int off, int len) throws IOException
{
if (current.method == STORED)
out.write(buf, off, len);
else
super.write(buf, off, len);
sum.update(buf, off, len);
uncompressed_size += len;
}
public void finish () throws IOException
{
if (current != null)
closeEntry ();
long offset = bytes_written;
int count = 0;
int bytes = 0;
while (chain != null)
{
bytes += write_entry (chain, false);
++count;
chain = chain.next;
}
put4 (0x06054b50);
put2 (0);
put2 (0);
put2 (count);
put2 (count);
put4 (bytes);
put4 ((int) offset);
byte[] c = comment.getBytes("8859_1");
put2 (c.length);
out.write(c);
}
private int write_entry (ZipEntry entry, boolean is_local)
throws IOException
{
int bytes = put4 (is_local ? 0x04034b50 : 0x02014b50);
if (! is_local)
bytes += put_version ();
bytes += put_version ();
boolean crc_after = false;
if (is_local
&& (entry.getCrc() == -1 || entry.getCompressedSize() == -1
|| entry.getSize() == -1))
crc_after = true;
bytes += put2 (crc_after ? (1 << 3) : 0);
bytes += put2 (entry.method);
bytes += put2(0); bytes += put2(0);
if (crc_after)
{
bytes += put4 (0);
bytes += put4 (0);
bytes += put4 (0);
}
else
{
bytes += put4 ((int) (entry.getCrc()));
bytes += put4 ((int) (entry.getCompressedSize()));
bytes += put4 ((int) (entry.getSize()));
}
byte[] name = entry.name.getBytes("8859_1");
bytes += put2 (name.length);
bytes += put2 (entry.extra == null ? 0 : entry.extra.length);
byte[] comment = null;
if (! is_local)
{
if (entry.getComment() == null)
bytes += put2 (0);
else
{
comment = entry.getComment().getBytes("8859_1");
bytes += put2 (comment.length);
}
bytes += put2 (0);
bytes += put2 (0);
bytes += put4 (0);
bytes += put4 ((int) entry.relativeOffset);
}
out.write (name);
bytes += name.length;
if (entry.extra != null)
{
out.write(entry.extra);
bytes += entry.extra.length;
}
if (comment != null)
{
out.write(comment);
bytes += comment.length;
}
bytes_written += bytes;
return bytes;
}
public void putNextEntry (ZipEntry entry) throws IOException
{
if (current != null)
closeEntry ();
if (entry.method < 0 )
entry.method = method;
if (entry.method == STORED)
{
if (entry.getSize() == -1 || entry.getCrc() == -1)
throw new ZipException ("required entry not set");
entry.compressedSize = entry.getSize();
}
entry.relativeOffset = bytes_written;
write_entry (entry, true);
current = entry;
int compr = (method == STORED) ? Deflater.NO_COMPRESSION : level;
def.reset();
def.setLevel(compr);
sum.reset();
uncompressed_size = 0;
}
public void setLevel (int level)
{
if (level != Deflater.DEFAULT_COMPRESSION
&& (level < Deflater.NO_COMPRESSION
|| level > Deflater.BEST_COMPRESSION))
throw new IllegalArgumentException ();
this.level = level;
}
public void setMethod (int method)
{
if (method != DEFLATED && method != STORED)
throw new IllegalArgumentException ();
this.method = method;
}
public void setComment (String comment)
{
if (comment.length() > 65535)
throw new IllegalArgumentException ();
this.comment = comment;
}
public ZipOutputStream (OutputStream out)
{
super (out, new Deflater (Deflater.DEFAULT_COMPRESSION, true), 8192);
sum = new CRC32 ();
}
private int put2 (int i) throws IOException
{
out.write (i);
out.write (i >> 8);
return 2;
}
private int put4 (int i) throws IOException
{
out.write (i);
out.write (i >> 8);
out.write (i >> 16);
out.write (i >> 24);
return 4;
}
private int put_version () throws IOException
{
return put2 (3 << 8);
}
private ZipEntry current;
private ZipEntry chain;
private int method = DEFLATED;
private int level = Deflater.DEFAULT_COMPRESSION;
private String comment = "";
private long bytes_written;
private int uncompressed_size;
private Checksum sum;
}