Strange behavior of ZipInputStream
I have a problem with ZipInputStream. Essentially, I receive and InputStream (that's why I cannot use ZipFile), and I need to unzip it and read all its entries. The problem is that the entries are xml files, so I need to build the dom, but when I call DocumentBuilder.parse, it reads all the input stream, and closes it. So, I've tried to read one entry at once, and parse it; but now it seems that ZipEntry.getSize() always returns a -1 length. Could someone explain me why? Also, do you know any good online resource about this? Because Ive done several searches but never found something useful. Thanks
ZipInputStream iz = new ZipInputStream( is ); // "is" is an InputStream
try
{
while( iz.available() == 1 )
{
ZipEntry entry = iz.getNextEntry();
if( entry != null )
if( entry.getSize() != -1 )
{
if( entry.getName().endsWith( "header.xml" ) )
{
long n = entry.getSize();
byte[] bytes = new byte[(int)n];
iz.read( bytes );
new ByteArrayInputStream( bytes );
XmlNode xml = new XmlNode( new ByteArrayInputStream( bytes ) ); // This calls DocumentBuilder.parse
project.setName( xml.path( "header/name" ).getValue( "Project" ) );
continue;
}
else
{
// do something
}
}
iz.close();
}
catch( IOException ioe )
{
ioe.printStackTrace();
}
[1424 byte] By [
yann74a] at [2007-11-27 7:14:34]

# 2
ZipEntry.getSize() , and all others getters, don't work well if the Stream is not a FileStream .
You may read the Input while until get a -1 .
try some like this
int i = 0, j = 0;
while((i=iz.read(bytes, j, Math.min(256, size-j))) > 0)
j += i;
# 5
It should, but it does not; I've put the code in a stand-alone class. You can compile it and launch it by specifying a zip file on the command line. I always get: Size of TestFileN: -1
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ZipTest
{
public static void main( String[] args )
{
try
{
parse( new FileInputStream( new File( args[0] ) ) );
}
catch( IndexOutOfBoundsException oe )
{
System.out.println( "No filename given" );
}
catch( FileNotFoundException e )
{
System.out.println( "File not found: " + args[0] );
}
}
public static void parse( InputStream is )
{
ZipInputStream iz = new ZipInputStream( is );
try
{
while( iz.available() == 1 )
{
ZipEntry entry = iz.getNextEntry();
if( entry != null )
{
System.out.println( "Size of " + entry.getName() + ": " + entry.getSize() );
}
}
iz.close();
}
catch( IOException ioe )
{
ioe.printStackTrace();
}
}
}
# 6
It does not always know the length of the zip entry. You can however extract the data for a given entry by just reading from the ZipInputStream until it returns -1. Then get the next entry.
The reason it does not know the length is that the zipEntry comes before the data but since the data is written in a streaming manner it does not know in advance how large it will be. By the time it does know it has normally flushed the segement of the stream containing the zipEntry. However it does insert markers into the stream to mark the end of zip entries which allows it to return -1 when you have read the stream.
more infor and examples here
http://java.sun.com/developer/technicalArticles/Programming/compression/
matfud