DeflaterOutputStream.java (deflate): Loop while def.needsInput.

* DeflaterOutputStream.java (deflate):  Loop while def.needsInput.
	(finish):  def.deflate needs to be called in a loop.
	(inbuf, inbufLength):  New private fields.
	(write(int)): Use inbuf.
	(write(byte[],int,int):  Check if pending output in inbuf.
	* ZipOutputStream.java:  Don't use Deflater if stored.
	Use a Checksum object directly, not via a CheckedOutputStream.
	(uncompressed_size):  New field,
	(closeEntry):  Only write data_directory if needed.
	(write):  If STORED, write directly.
	Always update crc, and uncompressed_size.
	(write_entry):  Fix lots of protocol erors.

From-SVN: r40988
This commit is contained in:
Per Bothner 2001-04-01 14:28:45 -07:00 committed by Per Bothner
parent aa9de837a8
commit f44b63ae02
3 changed files with 110 additions and 51 deletions

View File

@ -1,3 +1,18 @@
2001-04-01 Per Bothner <per@bothner.com>
* DeflaterOutputStream.java (deflate): Loop while def.needsInput.
(finish): def.deflate needs to be called in a loop.
(inbuf, inbufLength): New private fields.
(write(int)): Use inbuf.
(write(byte[],int,int): Check if pending output in inbuf.
* ZipOutputStream.java: Don't use Deflater if stored.
Use a Checksum object directly, not via a CheckedOutputStream.
(uncompressed_size): New field,
(closeEntry): Only write data_directory if needed.
(write): If STORED, write directly.
Always update crc, and uncompressed_size.
(write_entry): Fix lots of protocol erors.
2001-04-01 Bryce McKinlay <bryce@albatross.co.nz> 2001-04-01 Bryce McKinlay <bryce@albatross.co.nz>
1.3-Compliant Implementation of java.io.File. 1.3-Compliant Implementation of java.io.File.

View File

@ -50,13 +50,13 @@ public class DeflaterOutputStream extends FilterOutputStream
protected void deflate () throws IOException protected void deflate () throws IOException
{ {
while (true) do
{ {
int len = def.deflate(buf, 0, buf.length); int len = def.deflate(buf, 0, buf.length);
if (len == 0 || len == -1) if (len > 0)
break; out.write(buf, 0, len);
out.write(buf, 0, len); }
} while (! def.needsInput());
} }
public DeflaterOutputStream (OutputStream out) public DeflaterOutputStream (OutputStream out)
@ -78,23 +78,53 @@ public class DeflaterOutputStream extends FilterOutputStream
public void finish () throws IOException public void finish () throws IOException
{ {
if (inbufLength > 0)
{
def.setInput (inbuf, 0, inbufLength);
deflate ();
inbufLength = 0;
}
def.finish(); def.finish();
deflate (); while (! def.finished ())
{
int len = def.deflate(buf, 0, buf.length);
if (len > 0)
out.write(buf, 0, len);
}
} }
public void write (int bval) throws IOException public void write (int bval) throws IOException
{ {
byte[] b = new byte[1]; if (inbuf == null)
b[0] = (byte) bval; {
write (b, 0, 1); inbuf = new byte[128];
}
else if (inbufLength == inbuf.length)
{
def.setInput (inbuf, 0, inbufLength);
deflate ();
inbufLength = 0;
}
inbuf[inbufLength++] = (byte) bval;
} }
public void write (byte[] buf, int off, int len) throws IOException public void write (byte[] buf, int off, int len) throws IOException
{ {
if (inbufLength > 0)
{
def.setInput (inbuf, 0, inbufLength);
deflate ();
inbufLength = 0;
}
def.setInput (buf, off, len); def.setInput (buf, off, len);
deflate (); deflate ();
} }
// Used, if needed, for write(int).
private byte[] inbuf;
// Used length of inbuf.
private int inbufLength;
// The retrieval buffer. // The retrieval buffer.
protected byte[] buf; protected byte[] buf;

View File

@ -47,35 +47,62 @@ public class ZipOutputStream extends DeflaterOutputStream
public void closeEntry () throws IOException public void closeEntry () throws IOException
{ {
int uncompressed_size = def.getTotalIn(); int compressed_size;
int compressed_size = def.getTotalOut(); if (current.method == STORED)
long crc = filter.getChecksum().getValue(); {
compressed_size = uncompressed_size;
}
else
{
super.finish();
compressed_size = def.getTotalOut();
}
long crc = sum.getValue();
bytes_written += compressed_size; bytes_written += compressed_size;
bytes_written += put4 (0x08074b50);
if (current.getCrc() == -1 || current.getCompressedSize() == -1 if (current.getCrc() == -1 || current.getCompressedSize() == -1
|| current.getSize() == -1) || current.getSize() == -1)
{ {
current.setCrc(crc); current.setCrc(crc);
current.compressedSize = compressed_size; current.compressedSize = compressed_size;
current.setSize(uncompressed_size); current.setSize(uncompressed_size);
put4 (0x08074b50);
put4 ((int) (current.getCrc()));
put4 ((int) (current.getCompressedSize()));
put4 ((int) (current.getSize()));
bytes_written += 16;
} }
else else if (current.getCrc() != crc
{ || current.getCompressedSize() != compressed_size
if (current.getCrc() != crc || current.getSize() != uncompressed_size)
|| current.getCompressedSize() != compressed_size throw new ZipException ("zip entry field incorrect");
|| current.getSize() != uncompressed_size)
throw new ZipException ("zip entry field incorrect");
}
bytes_written += put4 ((int) (current.getCrc()));
bytes_written += put4 ((int) (current.getCompressedSize()));
bytes_written += put4 ((int) (current.getSize()));
current.next = chain; current.next = chain;
chain = current; chain = current;
current = null; current = null;
filter = 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 public void finish () throws IOException
@ -101,21 +128,19 @@ public class ZipOutputStream extends DeflaterOutputStream
// Another disk number. // Another disk number.
put2 (0); put2 (0);
put2 (count); put2 (count);
put2 (count);
put4 (bytes); put4 (bytes);
put4 ((int) offset); put4 ((int) offset);
byte[] c = comment.getBytes("8859_1"); byte[] c = comment.getBytes("8859_1");
put2 (c.length); put2 (c.length);
out.write(c); out.write(c);
out.write((byte) 0);
} }
// Helper for finish and putNextEntry. // Helper for finish and putNextEntry.
private int write_entry (ZipEntry entry, boolean is_local) private int write_entry (ZipEntry entry, boolean is_local)
throws IOException throws IOException
{ {
long offset = bytes_written;
int bytes = put4 (is_local ? 0x04034b50 : 0x02014b50); int bytes = put4 (is_local ? 0x04034b50 : 0x02014b50);
if (! is_local) if (! is_local)
bytes += put_version (); bytes += put_version ();
@ -169,25 +194,22 @@ public class ZipOutputStream extends DeflaterOutputStream
// Internal file attributes. // Internal file attributes.
bytes += put2 (0); bytes += put2 (0);
// External file attributes. // External file attributes.
bytes += put2 (0); bytes += put4 (0);
// Relative offset of local header. // Relative offset of local header.
bytes += put2 ((int) offset); bytes += put4 ((int) entry.relativeOffset);
} }
out.write (name); out.write (name);
out.write ((byte) 0); bytes += name.length;
bytes += name.length + 1;
if (entry.extra != null) if (entry.extra != null)
{ {
out.write(entry.extra); out.write(entry.extra);
out.write((byte) 0); bytes += entry.extra.length;
bytes += entry.extra.length + 1;
} }
if (comment != null) if (comment != null)
{ {
out.write(comment); out.write(comment);
out.write((byte) 0); bytes += comment.length;
bytes += comment.length + 1;
} }
bytes_written += bytes; bytes_written += bytes;
@ -208,13 +230,13 @@ public class ZipOutputStream extends DeflaterOutputStream
// Just in case. // Just in case.
entry.compressedSize = entry.getSize(); entry.compressedSize = entry.getSize();
} }
entry.relativeOffset = bytes_written;
write_entry (entry, true); write_entry (entry, true);
current = entry; current = entry;
int compr = (method == STORED) ? Deflater.NO_COMPRESSION : level; int compr = (method == STORED) ? Deflater.NO_COMPRESSION : level;
def.reset(); def.reset();
def.setLevel(compr); def.setLevel(compr);
filter = new CheckedOutputStream (new DeflaterOutputStream (out, def), sum.reset();
new CRC32 ());
} }
public void setLevel (int level) public void setLevel (int level)
@ -240,18 +262,10 @@ public class ZipOutputStream extends DeflaterOutputStream
this.comment = comment; this.comment = comment;
} }
public synchronized void write (byte[] buf, int off, int len)
throws IOException
{
if (filter == null)
throw new ZipException ("no open zip entry");
filter.write(buf, off, len);
}
public ZipOutputStream (OutputStream out) public ZipOutputStream (OutputStream out)
{ {
super (out); super (out, new Deflater (Deflater.DEFAULT_COMPRESSION, true), 8192);
def = new Deflater (level, true); sum = new CRC32 ();
} }
private int put2 (int i) throws IOException private int put2 (int i) throws IOException
@ -282,14 +296,14 @@ public class ZipOutputStream extends DeflaterOutputStream
private ZipEntry current; private ZipEntry current;
// The chain of entries which have been written to this file. // The chain of entries which have been written to this file.
private ZipEntry chain; private ZipEntry chain;
// The output stream to which data should be sent.
private CheckedOutputStream filter;
private int method = DEFLATED; private int method = DEFLATED;
private int level = Deflater.DEFAULT_COMPRESSION; private int level = Deflater.DEFAULT_COMPRESSION;
private String comment = ""; private String comment = "";
private long bytes_written; private long bytes_written;
// The Deflater we use. private int uncompressed_size;
private Deflater def;
/** The checksum object. */
private Checksum sum;
} }