Browse Source

First attempt at optimizing the zip code to have decent performance

The performance problem was mainly due to the entry insertion in
the hashtable where all hash code were equals in the hashtable.
I also removed a lot of unecessary Zip(Long|Short) object creation by
adding static methods and suppressed a hashtable. 

More can be done, but I tried not to break the interface and have as less code
as possible. The testcase attached in the bug report show that it is now 15% slower than Sun native code and 20% faster than Jazz libs.

Now watch for Gump...

PR: 31930


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277122 13f79535-47bb-0310-9956-ffa450edef68
master
Stephane Bailliez 20 years ago
parent
commit
a05d1f1219
6 changed files with 208 additions and 120 deletions
  1. +10
    -10
      src/main/org/apache/tools/zip/AsiExtraField.java
  2. +20
    -0
      src/main/org/apache/tools/zip/ZipEntry.java
  3. +59
    -37
      src/main/org/apache/tools/zip/ZipFile.java
  4. +37
    -13
      src/main/org/apache/tools/zip/ZipLong.java
  5. +50
    -54
      src/main/org/apache/tools/zip/ZipOutputStream.java
  6. +32
    -6
      src/main/org/apache/tools/zip/ZipShort.java

+ 10
- 10
src/main/org/apache/tools/zip/AsiExtraField.java View File

@@ -135,15 +135,15 @@ public class AsiExtraField implements ZipExtraField, UnixStat, Cloneable {
public byte[] getLocalFileDataData() {
// CRC will be added later
byte[] data = new byte[getLocalFileDataLength().getValue() - 4];
System.arraycopy((new ZipShort(getMode())).getBytes(), 0, data, 0, 2);
System.arraycopy(ZipShort.getBytes(getMode()), 0, data, 0, 2);

byte[] linkArray = getLinkedFile().getBytes();
System.arraycopy((new ZipLong(linkArray.length)).getBytes(),
System.arraycopy(ZipLong.getBytes(linkArray.length),
0, data, 2, 4);

System.arraycopy((new ZipShort(getUserId())).getBytes(),
System.arraycopy(ZipShort.getBytes(getUserId()),
0, data, 6, 2);
System.arraycopy((new ZipShort(getGroupId())).getBytes(),
System.arraycopy(ZipShort.getBytes(getGroupId()),
0, data, 8, 2);

System.arraycopy(linkArray, 0, data, 10, linkArray.length);
@@ -153,7 +153,7 @@ public class AsiExtraField implements ZipExtraField, UnixStat, Cloneable {
long checksum = crc.getValue();

byte[] result = new byte[data.length + 4];
System.arraycopy((new ZipLong(checksum)).getBytes(), 0, result, 0, 4);
System.arraycopy(ZipLong.getBytes(checksum), 0, result, 0, 4);
System.arraycopy(data, 0, result, 4, data.length);
return result;
}
@@ -282,7 +282,7 @@ public class AsiExtraField implements ZipExtraField, UnixStat, Cloneable {
public void parseFromLocalFileData(byte[] data, int offset, int length)
throws ZipException {

long givenChecksum = (new ZipLong(data, offset)).getValue();
long givenChecksum = ZipLong.getValue(data, offset);
byte[] tmp = new byte[length - 4];
System.arraycopy(data, offset + 4, tmp, 0, length - 4);
crc.reset();
@@ -295,10 +295,10 @@ public class AsiExtraField implements ZipExtraField, UnixStat, Cloneable {
+ Long.toHexString(realChecksum));
}

int newMode = (new ZipShort(tmp, 0)).getValue();
byte[] linkArray = new byte[(int) (new ZipLong(tmp, 2)).getValue()];
uid = (new ZipShort(tmp, 6)).getValue();
gid = (new ZipShort(tmp, 8)).getValue();
int newMode = ZipShort.getValue(tmp, 0);
byte[] linkArray = new byte[(int) ZipLong.getValue(tmp, 2)];
uid = ZipShort.getValue(tmp, 6);
gid = ZipShort.getValue(tmp, 8);

if (linkArray.length == 0) {
link = "";


+ 20
- 0
src/main/org/apache/tools/zip/ZipEntry.java View File

@@ -20,6 +20,8 @@ package org.apache.tools.zip;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Vector;
import java.util.Date;
import java.util.Calendar;
import java.util.zip.ZipException;

/**
@@ -386,6 +388,24 @@ public class ZipEntry extends java.util.zip.ZipEntry implements Cloneable {
this.name = name;
}

/**
* @since Ant 1.7
*/
public int hashCode(){
return getName().hashCode();
}

/**
* @since Ant 1.7
*/
public boolean equals(Object o){
if (o instanceof ZipEntry){
ZipEntry other = (ZipEntry)o;
return other.getName().equals(getName());
}
return false;
}

/**
* Helper for JDK 1.1
*


+ 59
- 37
src/main/org/apache/tools/zip/ZipFile.java View File

@@ -64,17 +64,17 @@ public class ZipFile {
* Maps ZipEntrys to Longs, recording the offsets of the local
* file headers.
*/
private Hashtable entries = new Hashtable();
private Hashtable entries = new Hashtable(509);

/**
* Maps String to ZipEntrys, name -> actual entry.
*/
private Hashtable nameMap = new Hashtable();
private Hashtable nameMap = new Hashtable(509);

/**
* Maps ZipEntrys to Longs, recording the offsets of the actual file data.
*/
private Hashtable dataOffsets = new Hashtable();
private static final class OffsetEntry {
long headerOffset = -1;
long dataOffset = - 1;
}

/**
* The encoding to use for filenames and the file comment.
@@ -201,12 +201,13 @@ public class ZipFile {
*/
public InputStream getInputStream(ZipEntry ze)
throws IOException, ZipException {
Long start = (Long) dataOffsets.get(ze);
if (start == null) {
OffsetEntry offsetEntry = (OffsetEntry)entries.get(ze);
if (offsetEntry == null){
return null;
}
long start = offsetEntry.dataOffset;
BoundedInputStream bis =
new BoundedInputStream(start.longValue(), ze.getCompressedSize());
new BoundedInputStream(start, ze.getCompressedSize());
switch (ze.getMethod()) {
case ZipEntry.STORED:
return bis;
@@ -253,57 +254,66 @@ public class ZipFile {

byte[] signatureBytes = new byte[4];
archive.readFully(signatureBytes);
ZipLong sig = new ZipLong(signatureBytes);
while (sig.equals(ZipOutputStream.CFH_SIG)) {
long sig = ZipLong.getValue(signatureBytes);
final long cfh_sig = ZipLong.getValue(ZipOutputStream.CFH_SIG);
while (sig == cfh_sig) {
archive.readFully(cfh);
int off = 0;
ZipEntry ze = new ZipEntry();

ZipShort versionMadeBy = new ZipShort(cfh, off);
int versionMadeBy = ZipShort.getValue(cfh, off);
off += 2;
ze.setPlatform((versionMadeBy.getValue() >> 8) & 0x0F);
ze.setPlatform((versionMadeBy >> 8) & 0x0F);

off += 4; // skip version info and general purpose byte

ze.setMethod((new ZipShort(cfh, off)).getValue());
ze.setMethod(ZipShort.getValue(cfh, off));
off += 2;

ze.setTime(fromDosTime(new ZipLong(cfh, off)).getTime());
// FIXME this is actually not very cpu cycles friendly as we are converting from
// dos to java while the underlying Sun implementation will convert
// from java to dos time for internal storage...
long time = dosToJavaTime(ZipLong.getValue(cfh, off));
ze.setTime(time);
off += 4;

ze.setCrc((new ZipLong(cfh, off)).getValue());
ze.setCrc(ZipLong.getValue(cfh, off));
off += 4;

ze.setCompressedSize((new ZipLong(cfh, off)).getValue());
ze.setCompressedSize(ZipLong.getValue(cfh, off));
off += 4;

ze.setSize((new ZipLong(cfh, off)).getValue());
ze.setSize(ZipLong.getValue(cfh, off));
off += 4;

int fileNameLen = (new ZipShort(cfh, off)).getValue();
int fileNameLen = ZipShort.getValue(cfh, off);
off += 2;

int extraLen = (new ZipShort(cfh, off)).getValue();
int extraLen = ZipShort.getValue(cfh, off);
off += 2;

int commentLen = (new ZipShort(cfh, off)).getValue();
int commentLen = ZipShort.getValue(cfh, off);
off += 2;

off += 2; // disk number

ze.setInternalAttributes((new ZipShort(cfh, off)).getValue());
ze.setInternalAttributes(ZipShort.getValue(cfh, off));
off += 2;

ze.setExternalAttributes((new ZipLong(cfh, off)).getValue());
ze.setExternalAttributes(ZipLong.getValue(cfh, off));
off += 4;

// LFH offset
entries.put(ze, new Long((new ZipLong(cfh, off)).getValue()));

byte[] fileName = new byte[fileNameLen];
archive.readFully(fileName);
ze.setName(getString(fileName));


// LFH offset,
OffsetEntry offset = new OffsetEntry();
offset.headerOffset = ZipLong.getValue(cfh, off);
// data offset will be filled later
entries.put(ze, offset);

nameMap.put(ze.getName(), ze);

archive.skipBytes(extraLen);
@@ -313,7 +323,7 @@ public class ZipFile {
ze.setComment(getString(comment));

archive.readFully(signatureBytes);
sig = new ZipLong(signatureBytes);
sig = ZipLong.getValue(signatureBytes);
}
}

@@ -352,7 +362,7 @@ public class ZipFile {
throws IOException {
long off = archive.length() - MIN_EOCD_SIZE;
archive.seek(off);
byte[] sig = ZipOutputStream.EOCD_SIG.getBytes();
byte[] sig = ZipOutputStream.EOCD_SIG;
int curr = archive.read();
boolean found = false;
while (curr != -1) {
@@ -378,7 +388,7 @@ public class ZipFile {
archive.seek(off + CFD_LOCATOR_OFFSET);
byte[] cfdOffset = new byte[4];
archive.readFully(cfdOffset);
archive.seek((new ZipLong(cfdOffset)).getValue());
archive.seek(ZipLong.getValue(cfdOffset));
}

/**
@@ -408,31 +418,42 @@ public class ZipFile {
Enumeration e = getEntries();
while (e.hasMoreElements()) {
ZipEntry ze = (ZipEntry) e.nextElement();
long offset = ((Long) entries.get(ze)).longValue();
OffsetEntry offsetEntry = (OffsetEntry)entries.get(ze);
long offset = offsetEntry.headerOffset;
archive.seek(offset + LFH_OFFSET_FOR_FILENAME_LENGTH);
byte[] b = new byte[2];
archive.readFully(b);
int fileNameLen = (new ZipShort(b)).getValue();
int fileNameLen = ZipShort.getValue(b);
archive.readFully(b);
int extraFieldLen = (new ZipShort(b)).getValue();
int extraFieldLen = ZipShort.getValue(b);
archive.skipBytes(fileNameLen);
byte[] localExtraData = new byte[extraFieldLen];
archive.readFully(localExtraData);
ze.setExtra(localExtraData);
dataOffsets.put(ze,
/*dataOffsets.put(ze,
new Long(offset + LFH_OFFSET_FOR_FILENAME_LENGTH
+ 2 + 2 + fileNameLen + extraFieldLen));
*/
offsetEntry.dataOffset = offset + LFH_OFFSET_FOR_FILENAME_LENGTH
+ 2 + 2 + fileNameLen + extraFieldLen;
}
}

/**
* Convert a DOS date/time field to a Date object.
*
* @param l contains the stored DOS time.
* @param zipDosTime contains the stored DOS time.
* @return a Date instance corresponding to the given time.
*/
protected static Date fromDosTime(ZipLong l) {
long dosTime = l.getValue();
protected static Date fromDosTime(ZipLong zipDosTime) {
long dosTime = zipDosTime.getValue();
return new Date(dosToJavaTime(dosTime));
}

/*
* Converts DOS time to Java time (number of milliseconds since epoch).
*/
private static long dosToJavaTime(long dosTime) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, (int) ((dosTime >> 25) & 0x7f) + 1980);
cal.set(Calendar.MONTH, (int) ((dosTime >> 21) & 0x0f) - 1);
@@ -440,9 +461,10 @@ public class ZipFile {
cal.set(Calendar.HOUR_OF_DAY, (int) (dosTime >> 11) & 0x1f);
cal.set(Calendar.MINUTE, (int) (dosTime >> 5) & 0x3f);
cal.set(Calendar.SECOND, (int) (dosTime << 1) & 0x3e);
return cal.getTime();
return cal.getTimeInMillis();
}


/**
* Retrieve a String from the given bytes using the encoding set
* for this ZipFile.


+ 37
- 13
src/main/org/apache/tools/zip/ZipLong.java View File

@@ -29,7 +29,6 @@ public final class ZipLong implements Cloneable {

/**
* Create instance from a number.
*
* @since 1.1
*/
public ZipLong(long value) {
@@ -38,7 +37,6 @@ public final class ZipLong implements Cloneable {

/**
* Create instance from bytes.
*
* @since 1.1
*/
public ZipLong (byte[] bytes) {
@@ -47,22 +45,34 @@ public final class ZipLong implements Cloneable {

/**
* Create instance from the four bytes starting at offset.
*
* @since 1.1
*/
public ZipLong (byte[] bytes, int offset) {
value = (bytes[offset + 3] << 24) & 0xFF000000L;
value += (bytes[offset + 2] << 16) & 0xFF0000;
value += (bytes[offset + 1] << 8) & 0xFF00;
value += (bytes[offset] & 0xFF);
value = ZipLong.getValue(bytes, offset);
}

/**
* Get value as two bytes in big endian byte order.
*
* Get value as four bytes in big endian byte order.
* @since 1.1
*/
public byte[] getBytes() {
return ZipLong.getBytes(value);
}

/**
* Get value as Java int.
* @since 1.1
*/
public long getValue() {
return value;
}

/**
* Get value as four bytes in big endian byte order.
* @param value the value to convert
* @return value as four bytes in big endian byte order
*/
public static byte[] getBytes(long value){
byte[] result = new byte[4];
result[0] = (byte) ((value & 0xFF));
result[1] = (byte) ((value & 0xFF00) >> 8);
@@ -72,14 +82,28 @@ public final class ZipLong implements Cloneable {
}

/**
* Get value as Java int.
*
* @since 1.1
* Helper method to get the value as a java long from four bytes starting at given array offset
* @param bytes the array of bytes
* @param offset the offset to start
* @return the correspondanding java int value
*/
public long getValue() {
public static long getValue(byte[] bytes, int offset){
long value = (bytes[offset + 3] << 24) & 0xFF000000L;
value += (bytes[offset + 2] << 16) & 0xFF0000;
value += (bytes[offset + 1] << 8) & 0xFF00;
value += (bytes[offset] & 0xFF);
return value;
}

/**
* Helper method to get the value as a java long from a four-byte array
* @param bytes the array of bytes
* @return the correspondanding java long value
*/
public static long getValue(byte[] bytes){
return getValue(bytes, 0);
}

/**
* Override to make two instances with same value equal.
*


+ 50
- 54
src/main/org/apache/tools/zip/ZipOutputStream.java View File

@@ -27,6 +27,7 @@ import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Calendar;
import java.util.zip.CRC32;
import java.util.zip.Deflater;
import java.util.zip.ZipException;
@@ -131,14 +132,14 @@ public class ZipOutputStream extends FilterOutputStream {
*
* @since 1.1
*/
private ZipLong cdOffset = new ZipLong(0);
private long cdOffset = 0;

/**
* Length of central directory.
*
* @since 1.1
*/
private ZipLong cdLength = new ZipLong(0);
private long cdLength = 0;

/**
* Helper, a 0 as ZipShort.
@@ -297,11 +298,11 @@ public class ZipOutputStream extends FilterOutputStream {
*/
public void finish() throws IOException {
closeEntry();
cdOffset = new ZipLong(written);
cdOffset = written;
for (int i = 0; i < entries.size(); i++) {
writeCentralFileHeader((ZipEntry) entries.elementAt(i));
}
cdLength = new ZipLong(written - cdOffset.getValue());
cdLength = written - cdOffset;
writeCentralDirectoryEnd();
offsets.clear();
entries.removeAllElements();
@@ -363,9 +364,9 @@ public class ZipOutputStream extends FilterOutputStream {
long save = raf.getFilePointer();

raf.seek(localDataStart);
writeOut((new ZipLong(entry.getCrc())).getBytes());
writeOut((new ZipLong(entry.getCompressedSize())).getBytes());
writeOut((new ZipLong(entry.getSize())).getBytes());
writeOut(ZipLong.getBytes(entry.getCrc()));
writeOut(ZipLong.getBytes(entry.getCompressedSize()));
writeOut(ZipLong.getBytes(entry.getSize()));
raf.seek(save);
}

@@ -517,25 +518,25 @@ public class ZipOutputStream extends FilterOutputStream {
*
* @since 1.1
*/
protected static final ZipLong LFH_SIG = new ZipLong(0X04034B50L);
protected static final byte[] LFH_SIG = ZipLong.getBytes(0X04034B50L);
/**
* data descriptor signature
*
* @since 1.1
*/
protected static final ZipLong DD_SIG = new ZipLong(0X08074B50L);
protected static final byte[] DD_SIG = ZipLong.getBytes(0X08074B50L);
/**
* central file header signature
*
* @since 1.1
*/
protected static final ZipLong CFH_SIG = new ZipLong(0X02014B50L);
protected static final byte[] CFH_SIG = ZipLong.getBytes(0X02014B50L);
/**
* end of central dir signature
*
* @since 1.1
*/
protected static final ZipLong EOCD_SIG = new ZipLong(0X06054B50L);
protected static final byte[] EOCD_SIG = ZipLong.getBytes(0X06054B50L);

/**
* Writes next block of compressed data to the output stream.
@@ -555,9 +556,9 @@ public class ZipOutputStream extends FilterOutputStream {
* @since 1.1
*/
protected void writeLocalFileHeader(ZipEntry ze) throws IOException {
offsets.put(ze, new ZipLong(written));
offsets.put(ze, ZipLong.getBytes(written));

writeOut(LFH_SIG.getBytes());
writeOut(LFH_SIG);
written += 4;

// version needed to extract
@@ -565,18 +566,18 @@ public class ZipOutputStream extends FilterOutputStream {
if (ze.getMethod() == DEFLATED && raf == null) {
// requires version 2 as we are going to store length info
// in the data descriptor
writeOut((new ZipShort(20)).getBytes());
writeOut(ZipShort.getBytes(20));

// bit3 set to signal, we use a data descriptor
writeOut((new ZipShort(8)).getBytes());
writeOut(ZipShort.getBytes(8));
} else {
writeOut((new ZipShort(10)).getBytes());
writeOut(ZipShort.getBytes(10));
writeOut(ZERO);
}
written += 4;

// compression method
writeOut((new ZipShort(ze.getMethod())).getBytes());
writeOut(ZipShort.getBytes(ze.getMethod()));
written += 2;

// last mod. time and date
@@ -592,20 +593,20 @@ public class ZipOutputStream extends FilterOutputStream {
writeOut(LZERO);
writeOut(LZERO);
} else {
writeOut((new ZipLong(ze.getCrc())).getBytes());
writeOut((new ZipLong(ze.getSize())).getBytes());
writeOut((new ZipLong(ze.getSize())).getBytes());
writeOut(ZipLong.getBytes(ze.getCrc()));
writeOut(ZipLong.getBytes(ze.getSize()));
writeOut(ZipLong.getBytes(ze.getSize()));
}
written += 12;

// file name length
byte[] name = getBytes(ze.getName());
writeOut((new ZipShort(name.length)).getBytes());
writeOut(ZipShort.getBytes(name.length));
written += 2;

// extra field length
byte[] extra = ze.getLocalFileDataExtra();
writeOut((new ZipShort(extra.length)).getBytes());
writeOut(ZipShort.getBytes(extra.length));
written += 2;

// file name
@@ -628,10 +629,10 @@ public class ZipOutputStream extends FilterOutputStream {
if (ze.getMethod() != DEFLATED || raf != null) {
return;
}
writeOut(DD_SIG.getBytes());
writeOut((new ZipLong(entry.getCrc())).getBytes());
writeOut((new ZipLong(entry.getCompressedSize())).getBytes());
writeOut((new ZipLong(entry.getSize())).getBytes());
writeOut(DD_SIG);
writeOut(ZipLong.getBytes(entry.getCrc()));
writeOut(ZipLong.getBytes(entry.getCompressedSize()));
writeOut(ZipLong.getBytes(entry.getSize()));
written += 16;
}

@@ -641,11 +642,11 @@ public class ZipOutputStream extends FilterOutputStream {
* @since 1.1
*/
protected void writeCentralFileHeader(ZipEntry ze) throws IOException {
writeOut(CFH_SIG.getBytes());
writeOut(CFH_SIG);
written += 4;

// version made by
writeOut((new ZipShort((ze.getPlatform() << 8) | 20)).getBytes());
writeOut(ZipShort.getBytes((ze.getPlatform() << 8) | 20));
written += 2;

// version needed to extract
@@ -653,18 +654,18 @@ public class ZipOutputStream extends FilterOutputStream {
if (ze.getMethod() == DEFLATED && raf == null) {
// requires version 2 as we are going to store length info
// in the data descriptor
writeOut((new ZipShort(20)).getBytes());
writeOut(ZipShort.getBytes(20));

// bit3 set to signal, we use a data descriptor
writeOut((new ZipShort(8)).getBytes());
writeOut(ZipShort.getBytes(8));
} else {
writeOut((new ZipShort(10)).getBytes());
writeOut(ZipShort.getBytes(10));
writeOut(ZERO);
}
written += 4;

// compression method
writeOut((new ZipShort(ze.getMethod())).getBytes());
writeOut(ZipShort.getBytes(ze.getMethod()));
written += 2;

// last mod. time and date
@@ -674,19 +675,19 @@ public class ZipOutputStream extends FilterOutputStream {
// CRC
// compressed length
// uncompressed length
writeOut((new ZipLong(ze.getCrc())).getBytes());
writeOut((new ZipLong(ze.getCompressedSize())).getBytes());
writeOut((new ZipLong(ze.getSize())).getBytes());
writeOut(ZipLong.getBytes(ze.getCrc()));
writeOut(ZipLong.getBytes(ze.getCompressedSize()));
writeOut(ZipLong.getBytes(ze.getSize()));
written += 12;

// file name length
byte[] name = getBytes(ze.getName());
writeOut((new ZipShort(name.length)).getBytes());
writeOut(ZipShort.getBytes(name.length));
written += 2;

// extra field length
byte[] extra = ze.getCentralDirectoryExtra();
writeOut((new ZipShort(extra.length)).getBytes());
writeOut(ZipShort.getBytes(extra.length));
written += 2;

// file comment length
@@ -695,7 +696,7 @@ public class ZipOutputStream extends FilterOutputStream {
comm = "";
}
byte[] commentB = getBytes(comm);
writeOut((new ZipShort(commentB.length)).getBytes());
writeOut(ZipShort.getBytes(commentB.length));
written += 2;

// disk number start
@@ -703,15 +704,15 @@ public class ZipOutputStream extends FilterOutputStream {
written += 2;

// internal file attributes
writeOut((new ZipShort(ze.getInternalAttributes())).getBytes());
writeOut(ZipShort.getBytes(ze.getInternalAttributes()));
written += 2;

// external file attributes
writeOut((new ZipLong(ze.getExternalAttributes())).getBytes());
writeOut(ZipLong.getBytes(ze.getExternalAttributes()));
written += 4;

// relative offset of LFH
writeOut(((ZipLong) offsets.get(ze)).getBytes());
writeOut((byte[]) offsets.get(ze));
written += 4;

// file name
@@ -733,24 +734,24 @@ public class ZipOutputStream extends FilterOutputStream {
* @since 1.1
*/
protected void writeCentralDirectoryEnd() throws IOException {
writeOut(EOCD_SIG.getBytes());
writeOut(EOCD_SIG);

// disk numbers
writeOut(ZERO);
writeOut(ZERO);

// number of entries
byte[] num = (new ZipShort(entries.size())).getBytes();
byte[] num = ZipShort.getBytes(entries.size());
writeOut(num);
writeOut(num);

// length and location of CD
writeOut(cdLength.getBytes());
writeOut(cdOffset.getBytes());
writeOut(ZipLong.getBytes(cdLength));
writeOut(ZipLong.getBytes(cdOffset));

// ZIP file comment
byte[] data = getBytes(comment);
writeOut((new ZipShort(data.length)).getBytes());
writeOut(ZipShort.getBytes(data.length));
writeOut(data);
}

@@ -759,7 +760,7 @@ public class ZipOutputStream extends FilterOutputStream {
*
* @since 1.1
*/
private static final ZipLong DOS_TIME_MIN = new ZipLong(0x00002100L);
private static final byte[] DOS_TIME_MIN = ZipLong.getBytes(0x00002100L);

/**
* Convert a Date object to a DOS date/time field.
@@ -781,7 +782,7 @@ public class ZipOutputStream extends FilterOutputStream {
Date time = new Date(t);
int year = time.getYear() + 1900;
if (year < 1980) {
return DOS_TIME_MIN.getBytes();
return DOS_TIME_MIN;
}
int month = time.getMonth() + 1;
long value = ((year - 1980) << 25)
@@ -790,12 +791,7 @@ public class ZipOutputStream extends FilterOutputStream {
| (time.getHours() << 11)
| (time.getMinutes() << 5)
| (time.getSeconds() >> 1);
byte[] result = new byte[4];
result[0] = (byte) ((value & 0xFF));
result[1] = (byte) ((value & 0xFF00) >> 8);
result[2] = (byte) ((value & 0xFF0000) >> 16);
result[3] = (byte) ((value & 0xFF000000L) >> 24);
return result;
return ZipLong.getBytes(value);
}

/**


+ 32
- 6
src/main/org/apache/tools/zip/ZipShort.java View File

@@ -38,7 +38,6 @@ public final class ZipShort implements Cloneable {

/**
* Create instance from bytes.
*
* @since 1.1
*/
public ZipShort (byte[] bytes) {
@@ -47,17 +46,14 @@ public final class ZipShort implements Cloneable {

/**
* Create instance from the two bytes starting at offset.
*
* @since 1.1
*/
public ZipShort (byte[] bytes, int offset) {
value = (bytes[offset + 1] << 8) & 0xFF00;
value += (bytes[offset] & 0xFF);
value = ZipShort.getValue(bytes, offset);
}

/**
* Get value as two bytes in big endian byte order.
*
* @since 1.1
*/
public byte[] getBytes() {
@@ -69,13 +65,43 @@ public final class ZipShort implements Cloneable {

/**
* Get value as Java int.
*
* @since 1.1
*/
public int getValue() {
return value;
}

/**
* Get value as two bytes in big endian byte order.
*/
public static byte[] getBytes(int value){
byte[] result = new byte[2];
result[0] = (byte) (value & 0xFF);
result[1] = (byte) ((value & 0xFF00) >> 8);
return result;
}

/**
* Helper method to get the value as a java int from two bytes starting at given array offset
* @param bytes the array of bytes
* @param offset the offset to start
* @return the correspondanding java int value
*/
public static int getValue(byte[] bytes, int offset){
int value = (bytes[offset + 1] << 8) & 0xFF00;
value += (bytes[offset] & 0xFF);
return value;
}

/**
* Helper method to get the value as a java int from a two-byte array
* @param bytes the array of bytes
* @return the correspondanding java int value
*/
public static int getValue(byte[] bytes){
return getValue(bytes, 0);
}

/**
* Override to make two instances with same value equal.
*


Loading…
Cancel
Save