ZipOutputStream.java (level): Initial value is Deflater.DEFAULT_COMPRESSION.
* java/util/zip/ZipOutputStream.java (level): Initial value is Deflater.DEFAULT_COMPRESSION. (close): New method. (closeEntry): Likewise. (finish): Likewise. (put_version): Likewise. (write_entry): Likewise. (put2, put4): Now return `int'. (comment): Default to empty string. (bytes_written): New instance variable. (chain): Likewise. * java/util/zip/ZipEntry.java (setComment): Limit length of comment string. (setCrc): Check CRC validity. (setExtra): Check argument validity. (setMethod): Likewise. (setSize): Likewise. (ZipEntry): Likewise. * include/javaprims.h: Updated namespace declarations. * Makefile.in: Rebuilt. * Makefile.am (ordinary_java_source_files): Mention new files. (nat_source_files): Likewise. * java/util/zip/ZipFile.java (readu2): Throw ZipException, not EOFException. (read4): Likewise. (getInputStream): Handle compressed entries. * java/util/zip/GZIPOutputStream.java: New file. * java/util/zip/GZIPInputStream.java: New file. * java/util/zip/DataFormatException.java: New file. * java/util/zip/CheckedInputStream.java: New file. * java/util/zip/CheckedOutputStream.java: New file. * java/util/zip/InflaterInputStream.java: Implemented. * java/util/zip/natInflater.cc: New file. * java/util/zip/Deflater.java: Implemented. * java/util/zip/natDeflater.cc: New file. * java/util/zip/DeflaterOutputStream.java: Implemented. * java/util/zip/ZipInputStream.java (closeZipEntry): Throw ZipException, not IOException. * java/util/zip/ZipFile.java (readDirectory): Throw ZipException, not IOException. From-SVN: r26996
This commit is contained in:
parent
5a9e5c6fb6
commit
0ffac8322f
19 changed files with 1555 additions and 80 deletions
|
@ -9,65 +9,268 @@ details. */
|
|||
package java.util.zip;
|
||||
import java.io.*;
|
||||
|
||||
/** JUST AN INCOMPLETE STUB! */
|
||||
/* Written using on-line Java Platform 1.2 API Specification
|
||||
* and JCL book.
|
||||
* Believed complete and correct.
|
||||
*/
|
||||
|
||||
public class ZipOutputStream extends DeflaterOutputStream
|
||||
implements ZipConstants
|
||||
{
|
||||
ZipEntry current;
|
||||
int method = DEFLATED;
|
||||
int level = 3; // FIXME - should be DEFAULT_COMPRESSION
|
||||
String comment;
|
||||
|
||||
public static final int STORED = 0;
|
||||
public static final int DEFLATED = 8;
|
||||
|
||||
public ZipOutputStream (OutputStream out)
|
||||
public void close () throws IOException
|
||||
{
|
||||
super(out);
|
||||
}
|
||||
|
||||
public void setLevel (int level) { this.level = level; }
|
||||
public void setMethod (int method) { this.method = method; }
|
||||
public void setComment(String comment) { this.comment = comment; }
|
||||
|
||||
public void putNextEntry (ZipEntry entry) throws IOException
|
||||
{
|
||||
put4(0x04034b50);
|
||||
put2(0); // version - FIXME
|
||||
put2(0); // bits - FIXME
|
||||
if (entry.method < 0 )
|
||||
entry.method = method;
|
||||
put2(entry.method);
|
||||
put2(0); // time - FIXME
|
||||
put2(0); // date - FIXME
|
||||
put4((int) entry.crc);
|
||||
put4((int) entry.compressedSize); // FIXME
|
||||
put4((int) entry.size); // FIXME
|
||||
put2(entry.name.length());
|
||||
put2(entry.extra == null ? 0 : entry.extra.length);
|
||||
byte[] name = entry.name.getBytes("8859_1");
|
||||
out.write(name);
|
||||
if (entry.extra != null)
|
||||
out.write(entry.extra);
|
||||
throw new Error ("java.util.zip.ZipOutputStream.putNextEntry: not implemented");
|
||||
finish ();
|
||||
out.close();
|
||||
}
|
||||
|
||||
public void closeEntry () throws IOException
|
||||
{
|
||||
int uncompressed_size = def.getTotalIn();
|
||||
int compressed_size = def.getTotalOut();
|
||||
int crc = (int) (filter.getChecksum().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);
|
||||
}
|
||||
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()));
|
||||
|
||||
current.next = chain;
|
||||
chain = current;
|
||||
current = null;
|
||||
filter = null;
|
||||
}
|
||||
|
||||
private void put2 (int i) throws IOException
|
||||
public void finish () throws IOException
|
||||
{
|
||||
if (current != null)
|
||||
closeEntry ();
|
||||
|
||||
// Write the central directory.
|
||||
long offset = bytes_written;
|
||||
int count = 0;
|
||||
int bytes = 0;
|
||||
while (chain != null)
|
||||
{
|
||||
bytes += write_entry (chain, false);
|
||||
++count;
|
||||
chain = chain.next;
|
||||
}
|
||||
|
||||
// Write the end of the central directory record.
|
||||
put4 (0x06054b50);
|
||||
// Disk number.
|
||||
put2 (0);
|
||||
// Another disk number.
|
||||
put2 (0);
|
||||
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 ();
|
||||
bytes += put_version ();
|
||||
|
||||
boolean crc_after = false;
|
||||
if (is_local
|
||||
&& (current.getCrc() == -1 || current.getCompressedSize() == -1
|
||||
|| current.getSize() == -1))
|
||||
crc_after = true;
|
||||
// For the bits field we always indicate `normal' compression,
|
||||
// even if that isn't true.
|
||||
bytes += put2 (crc_after ? (1 << 3) : 0);
|
||||
bytes += put2 (entry.method);
|
||||
|
||||
bytes += put2(0); // time - FIXME
|
||||
bytes += put2(0); // date - FIXME
|
||||
|
||||
if (crc_after)
|
||||
{
|
||||
// CRC, compressedSize, and Size are always 0 in this header.
|
||||
// The actual values are given after the entry.
|
||||
bytes += put4 (0);
|
||||
bytes += put4 (0);
|
||||
bytes += put4 (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes += put4 ((int) (entry.getCrc()));
|
||||
bytes += put4 ((int) (entry.getCompressedSize()));
|
||||
bytes += put4 ((int) (entry.getSize()));
|
||||
}
|
||||
|
||||
byte[] name = entry.name.getBytes("8859_1");
|
||||
bytes += put2 (name.length);
|
||||
bytes += put2 (entry.extra == null ? 0 : entry.extra.length);
|
||||
|
||||
byte[] comment = null;
|
||||
if (! is_local)
|
||||
{
|
||||
if (entry.getComment() == null)
|
||||
bytes += put2 (0);
|
||||
else
|
||||
{
|
||||
comment = entry.getComment().getBytes("8859_1");
|
||||
bytes += put2 (comment.length);
|
||||
}
|
||||
|
||||
// Disk number start.
|
||||
bytes += put2 (0);
|
||||
// Internal file attributes.
|
||||
bytes += put2 (0);
|
||||
// External file attributes.
|
||||
bytes += put2 (0);
|
||||
// Relative offset of local header.
|
||||
bytes += put2 ((int) offset);
|
||||
}
|
||||
|
||||
out.write (name);
|
||||
out.write ((byte) 0);
|
||||
bytes += name.length + 1;
|
||||
if (entry.extra != null)
|
||||
{
|
||||
out.write(entry.extra);
|
||||
out.write((byte) 0);
|
||||
bytes += entry.extra.length + 1;
|
||||
}
|
||||
if (comment != null)
|
||||
{
|
||||
out.write(comment);
|
||||
out.write((byte) 0);
|
||||
bytes += comment.length + 1;
|
||||
}
|
||||
|
||||
bytes_written += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public void putNextEntry (ZipEntry entry) throws IOException
|
||||
{
|
||||
if (current != null)
|
||||
closeEntry ();
|
||||
|
||||
if (entry.method < 0 )
|
||||
entry.method = method;
|
||||
if (entry.method == STORED)
|
||||
{
|
||||
if (entry.getSize() == -1 || entry.getCrc() == -1)
|
||||
throw new ZipException ("required entry not set");
|
||||
// Just in case.
|
||||
entry.compressedSize = entry.getSize();
|
||||
}
|
||||
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 ());
|
||||
}
|
||||
|
||||
public void setLevel (int level)
|
||||
{
|
||||
if (level != Deflater.DEFAULT_COMPRESSION
|
||||
&& (level < Deflater.NO_COMPRESSION
|
||||
|| level > Deflater.BEST_COMPRESSION))
|
||||
throw new IllegalArgumentException ();
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public void setMethod (int method)
|
||||
{
|
||||
if (method != DEFLATED && method != STORED)
|
||||
throw new IllegalArgumentException ();
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public void setComment (String comment)
|
||||
{
|
||||
if (comment.length() > 65535)
|
||||
throw new IllegalArgumentException ();
|
||||
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);
|
||||
}
|
||||
|
||||
private int put2 (int i) throws IOException
|
||||
{
|
||||
out.write (i);
|
||||
out.write (i >> 8);
|
||||
return 2;
|
||||
}
|
||||
|
||||
private void put4 (int i) throws IOException
|
||||
private int put4 (int i) throws IOException
|
||||
{
|
||||
out.write (i);
|
||||
out.write (i >> 8);
|
||||
out.write (i >> 16);
|
||||
out.write (i >> 24);
|
||||
return 4;
|
||||
}
|
||||
|
||||
private int put_version () throws IOException
|
||||
{
|
||||
// FIXME: for now we assume Unix, and we ignore the version
|
||||
// number.
|
||||
return put2 (3 << 8);
|
||||
}
|
||||
|
||||
// The entry we are currently writing, or null if we've called
|
||||
// closeEntry.
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue