From f44b63ae02d689ccf33f66022228ee8d7145cfd8 Mon Sep 17 00:00:00 2001 From: Per Bothner Date: Sun, 1 Apr 2001 14:28:45 -0700 Subject: [PATCH] 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 --- libjava/ChangeLog | 15 +++ .../java/util/zip/DeflaterOutputStream.java | 48 +++++++-- libjava/java/util/zip/ZipOutputStream.java | 98 +++++++++++-------- 3 files changed, 110 insertions(+), 51 deletions(-) diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 84aacc9e969..3c1ef115410 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,18 @@ +2001-04-01 Per Bothner + + * 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 1.3-Compliant Implementation of java.io.File. diff --git a/libjava/java/util/zip/DeflaterOutputStream.java b/libjava/java/util/zip/DeflaterOutputStream.java index d4218fa5cc5..7a1dbb2cf66 100644 --- a/libjava/java/util/zip/DeflaterOutputStream.java +++ b/libjava/java/util/zip/DeflaterOutputStream.java @@ -50,13 +50,13 @@ public class DeflaterOutputStream extends FilterOutputStream protected void deflate () throws IOException { - while (true) + do { int len = def.deflate(buf, 0, buf.length); - if (len == 0 || len == -1) - break; - out.write(buf, 0, len); - } + if (len > 0) + out.write(buf, 0, len); + } + while (! def.needsInput()); } public DeflaterOutputStream (OutputStream out) @@ -78,23 +78,53 @@ public class DeflaterOutputStream extends FilterOutputStream public void finish () throws IOException { + if (inbufLength > 0) + { + def.setInput (inbuf, 0, inbufLength); + deflate (); + inbufLength = 0; + } 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 { - byte[] b = new byte[1]; - b[0] = (byte) bval; - write (b, 0, 1); + if (inbuf == null) + { + 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 { + if (inbufLength > 0) + { + def.setInput (inbuf, 0, inbufLength); + deflate (); + inbufLength = 0; + } def.setInput (buf, off, len); deflate (); } + // Used, if needed, for write(int). + private byte[] inbuf; + // Used length of inbuf. + private int inbufLength; + // The retrieval buffer. protected byte[] buf; diff --git a/libjava/java/util/zip/ZipOutputStream.java b/libjava/java/util/zip/ZipOutputStream.java index a0a8ed744bb..bcbc59154fb 100644 --- a/libjava/java/util/zip/ZipOutputStream.java +++ b/libjava/java/util/zip/ZipOutputStream.java @@ -47,35 +47,62 @@ public class ZipOutputStream extends DeflaterOutputStream public void closeEntry () throws IOException { - int uncompressed_size = def.getTotalIn(); - int compressed_size = def.getTotalOut(); - long crc = filter.getChecksum().getValue(); + 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; - bytes_written += put4 (0x08074b50); 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"); - } - bytes_written += put4 ((int) (current.getCrc())); - bytes_written += put4 ((int) (current.getCompressedSize())); - bytes_written += put4 ((int) (current.getSize())); + 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; - 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 @@ -101,21 +128,19 @@ public class ZipOutputStream extends DeflaterOutputStream // Another disk number. put2 (0); put2 (count); + put2 (count); put4 (bytes); put4 ((int) offset); byte[] c = comment.getBytes("8859_1"); put2 (c.length); out.write(c); - out.write((byte) 0); } // Helper for finish and putNextEntry. private int write_entry (ZipEntry entry, boolean is_local) throws IOException { - long offset = bytes_written; - int bytes = put4 (is_local ? 0x04034b50 : 0x02014b50); if (! is_local) bytes += put_version (); @@ -169,25 +194,22 @@ public class ZipOutputStream extends DeflaterOutputStream // Internal file attributes. bytes += put2 (0); // External file attributes. - bytes += put2 (0); + bytes += put4 (0); // Relative offset of local header. - bytes += put2 ((int) offset); + bytes += put4 ((int) entry.relativeOffset); } out.write (name); - out.write ((byte) 0); - bytes += name.length + 1; + bytes += name.length; if (entry.extra != null) { out.write(entry.extra); - out.write((byte) 0); - bytes += entry.extra.length + 1; + bytes += entry.extra.length; } if (comment != null) { out.write(comment); - out.write((byte) 0); - bytes += comment.length + 1; + bytes += comment.length; } bytes_written += bytes; @@ -208,13 +230,13 @@ public class ZipOutputStream extends DeflaterOutputStream // Just in case. 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); - filter = new CheckedOutputStream (new DeflaterOutputStream (out, def), - new CRC32 ()); + sum.reset(); } public void setLevel (int level) @@ -240,18 +262,10 @@ public class ZipOutputStream extends DeflaterOutputStream 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) { - super (out); - def = new Deflater (level, true); + super (out, new Deflater (Deflater.DEFAULT_COMPRESSION, true), 8192); + sum = new CRC32 (); } private int put2 (int i) throws IOException @@ -282,14 +296,14 @@ public class ZipOutputStream extends DeflaterOutputStream private ZipEntry current; // The chain of entries which have been written to this file. private ZipEntry chain; - // The output stream to which data should be sent. - private CheckedOutputStream filter; private int method = DEFLATED; private int level = Deflater.DEFAULT_COMPRESSION; private String comment = ""; private long bytes_written; - // The Deflater we use. - private Deflater def; + private int uncompressed_size; + + /** The checksum object. */ + private Checksum sum; } -- 2.30.2