DeflaterOutputStream.java (deflate): Loop while def.needsInput.
authorPer Bothner <per@bothner.com>
Sun, 1 Apr 2001 21:28:45 +0000 (14:28 -0700)
committerPer Bothner <bothner@gcc.gnu.org>
Sun, 1 Apr 2001 21:28:45 +0000 (14:28 -0700)
* 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
libjava/java/util/zip/DeflaterOutputStream.java
libjava/java/util/zip/ZipOutputStream.java

index 84aacc9e969a936b9cd55e1adc841af7f6ab380b..3c1ef11541094aea6a791a6e7f43753451818d55 100644 (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>
 
        1.3-Compliant Implementation of java.io.File.
index d4218fa5cc5d068381238d644ade6e5d64069dfc..7a1dbb2cf66333bdf71d0d1c30fa7cdc764636a8 100644 (file)
@@ -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;
 
index a0a8ed744bb9fb5611f7c099bf98d3c4cb005b48..bcbc59154fb89bfb74547012081f17508b7507a8 100644 (file)
@@ -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;
 }