JDK-6285124 : Small compressed zip entries should be read in one read() operation
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.jar
  • Affected Version: 5.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2005-06-14
  • Updated: 2010-05-04
  • Resolved: 2005-08-10
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6
5.0u7Fixed 6 b47Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_03-b07)
Java HotSpot(TM) Client VM (build 1.5.0_03-b07, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows 2000 [Version 5.00.2195]


A DESCRIPTION OF THE PROBLEM :
When I compress text string "Data disponible" using ZipOutputStream class and uncompress it using ZipFile class the uncompressed result lost the last byte and replace it with a null char.

If I used other text with more bytes, I have no problem.

I think we have this problem only with a data that the compressed result is greather than the uncompressed data. In our case, uncompress data is 15 bytes and compress data is 17 bytes.




STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and execute the source code and check the result.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Uncompress result should be exactly the same as before compression.
ACTUAL -
Content:Data disponibl

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------

import java.io.*;
import java.util.zip.*;

public class TestZip
{
   public TestZip()
   {
      try
      {
         // Create a working dir
         File dir = new File("c:\\temp\\testzip");
         dir.delete();
         dir.mkdir();

         // Create a file to compress
         File file = new File(dir, "abc.txt");
         FileWriter writer = new FileWriter(file);
         writer.write("Data disponible");
         writer.close();

         // Compress file
         zip(new File("c:\\temp\\testzip\\abc.zip"), file);

         // Uncompress file and check the content.
         ZipFile zipFile = new ZipFile(new File("c:\\temp\\testzip\\abc.zip"));
         InputStream inputStream = zipFile.getInputStream(zipFile.getEntry("abc.txt"));

         byte[] content = new byte[inputStream.available()];
         inputStream.read(content);
         System.out.println("Content:" + new String(content));

         zipFile.close();
      }
      catch (Exception ex)
      {
         ex.printStackTrace();
      }
   }

   private void zip(final File aZipFileName, final File aFile) throws IOException
   {
      final int BUFFER = 2048;

      BufferedInputStream origin = new BufferedInputStream(new FileInputStream(aFile));

      ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(aZipFileName)));
      zip.putNextEntry(new ZipEntry(aFile.getName()));

      int count;
      byte data[] = new byte[BUFFER];
      while((count = origin.read(data, 0, BUFFER)) != -1)
      {
         zip.write(data, 0, count);
      }

      origin.close();
      zip.closeEntry();
      zip.close();
   }

   public static void main(String[] args)
   {
      TestZip testzip = new TestZip();
   }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
I don't known.
###@###.### 2005-06-14 09:05:09 GMT

Comments
SUGGESTED FIX --- /tmp/geta22633 2005-07-21 19:35:57.800290000 -0700 +++ ZipFile.java 2005-07-21 19:34:16.501103000 -0700 @@ -310,15 +310,15 @@ } final ZipFileInputStream zfin = in; switch (getMethod(jzentry)) { case STORED: return zfin; case DEFLATED: // MORE: Compute good size for inflater stream: - long size = getSize(jzentry); + long size = getSize(jzentry)+2; // Inflater likes a bit of slack if (size > 65536) size = 8192; if (size <= 0) size = 4096; return new InflaterInputStream(zfin, getInflater(), (int)size) { private boolean isClosed = false; public void close() throws IOException { if (!isClosed) { ###@###.### 2005-07-22 02:36:11 GMT ###@###.### 2005-07-22 02:36:40 GMT
22-07-2005

EVALUATION Confirmed on Solaris, from Tiger update 2 onward. ###@###.### 2005-07-21 22:09:57 GMT First, let's make clear that read() can return short, i.e. there is no guarantee that read will always return the number of bytes available. Nevertheless, it is reasonable to expect a read when 15 bytes are available to return 15, not 14. The failure appears to have been introduced by 4974531 : classes are loaded 512 bytes at a time, slowing down applet start time It appears that Inflaters need a bit of slack in their buffer, so let's give it to them. Increasing the size of the buffer by a few bytes fixes the problem, empirically. ###@###.### 2005-07-22 02:36:11 GMT
21-07-2005