|
Quick Lists
|
|
Bug ID:
|
4109069
|
|
Votes
|
0
|
|
Synopsis
|
java.util.zip.InflaterInputStream available() and read(byte[]) are broken
|
|
Category
|
java:classes_util
|
|
Reported Against
|
1.2beta2
, 1.2beta4
, swing1.0.2
|
|
Release Fixed
|
1.2(1.2fcs)
|
|
State
|
11-Closed,
Unverified,
bug
|
|
Priority:
|
4-Low
|
|
Related Bugs
|
4028605
,
4182189
,
4675817
|
|
Submit Date
|
03-FEB-1998
|
|
Description
|
/*
java.util.zip.InflaterInputStream.available()
doesn't return the correct number of bytes.
Also, java.util.zip.InflaterInputStream.read(byte[])
doesn't correctly read the file even if passed the
correct number of bytes.
The the test code to work, swing.jar and JFrame.class
must both be in the directory from which you run the
code.
*/
import java.io.*;
import java.util.zip.*;
class JarInput {
static final String JAR_FILE = "swing.jar";
static final String CLASS_FILE = "com/sun/java/swing/JFrame.class";
static final String DOS_FILE = "JFrame.class";
static final String DEBUG_FILE = "debug.txt";
static PrintWriter debugWriter;
public static void main(String[] args) {
try {
ZipFile zipFile = new ZipFile(JAR_FILE);
ZipEntry zipEntry = zipFile.getEntry(CLASS_FILE);
int realFileSize;
//Get InputStream from a class file...
FileInputStream fis = new FileInputStream(DOS_FILE);
//Print the size reported by available() and dump FileInputStream
realFileSize = fis.available();
print("From class file => " + fis + " available=" + realFileSize);
print("Printing the FileInputStream from class file");
print(fis);
//Get InputStream from jar file...
InputStream is = zipFile.getInputStream(zipEntry);
int wrongFileSize = is.available();
byte[] buff = new byte[realFileSize]; //Don't rely on InflaterInputStream.available()
is.read(buff);
ByteArrayInputStream bis = new ByteArrayInputStream(buff);
//Print the size reported by available() and dump ByteArrayInputStream
print("From Jar => " + is + " available=" + wrongFileSize);
print("Printing the ByteArrayInputStream from jar file");
print(bis);
}
catch(IOException ex) {
System.out.println(ex);
}
}
static final void print(InputStream is)
throws IOException
{
int aByte;
StringBuffer strBuf = new StringBuffer();
int colPos = 0;
int colMax = 16;
while((aByte = is.read()) != -1) {
strBuf.append(" " + int2Hex(aByte));
colPos++;
if (colPos == 8) {
strBuf.append(" ");
}
else if(colPos == colMax) {
strBuf.append("\n");
colPos = 0;
}
}
print(strBuf.toString());
}
static String int2Hex(int i) {
int j = i / 16;
int k = i % 16;
return digit2Hex(j) + digit2Hex(k);
}
static String digit2Hex(int i) {
switch(i) {
case 0 : return "0";
case 1 : return "1";
case 2 : return "2";
case 3 : return "3";
case 4 : return "4";
case 5 : return "5";
case 6 : return "6";
case 7 : return "7";
case 8 : return "8";
case 9 : return "9";
case 10 : return "A";
case 11 : return "B";
case 12 : return "C";
case 13 : return "D";
case 14 : return "E";
case 15 : return "F";
default:
throw new RuntimeException(i + " can't be translated to a hex digit");
}
}
static {
try {
debugWriter = new PrintWriter(new FileOutputStream(DEBUG_FILE), true);
}
catch(IOException e) {
System.err.println(DEBUG_FILE + " : " + e);
System.exit(1);
debugWriter = new PrintWriter(System.err, true);
}
}
static final void print(String string) {
debugWriter.println(string);
}
}
(Review ID: 24345)
======================================================================
|
|
Work Around
|
Read the InflaterInputStream one byte at a time.
======================================================================
|
|
Evaluation
|
Programs should never expect read to read all
the available bytes from the underlying stream. According to JLS
22.3.2,f or read(b), "the number of bytes read is, at most, equal
to the length of b", so the right way to do is to check the
return value of read to see how much data was actually read.
In general, an InflaterInputStream available is not able to return the
exact number of bytes that are available from the compressed file.
With the fix to bug 4028605, ZipInputStream and InflaterInputStream
available will always return 1 before EOF and 0 otherwise. So available
can be used to see whether EOF has reached of not, and the return
value of read() needs to be checked.
xxxxx@xxxxx 1998-07-21
|
|
Comments
|
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|
|
|
 |