java2.util2.zip2.ZipOutputStream: 93.13%
Overview
Search Parameters
- plot: false
- chromosome_length: 40
- static_hack: false
- tournament_size: 10
- max_int: 2048
- string_length: 20
- crossover_rate: 0.75
- max_attempts: 1000
- CP: build/classes
- check_parents_length: true
- PREFIX: java2.util2.zip2
- stopping_condition: MaxStatements
- max_recursion: 10
- primitive_pool: 0.5
- selection_function: Rank
- generations: 2000000
- primitive_reuse_probability: 0.5
- test_excludes: test.excludes
- bloat_factor: 2
- object_reuse_probability: 0.9
- minimize: true
- html: true
- null_probability: 0.1
- strategy: EvoSuite
- elite: 1
- check_best_length: true
- num_tests: 2
- PROJECT_PREFIX: java2.util2.zip2
- OUTPUT_DIR: evosuite-files
- algorithm: SteadyStateGA
- string_replacement: true
- crossover_function: SinglePointRelative
- report_dir: evosuite-report
- test_includes: test.includes
- output_dir: evosuite-files
- criterion: branch
- rank_bias: 1.7
- timeout: 5000
- population: 100
- test_dir: evosuite-tests
- max_size: 100
- check_max_length: true
- TARGET_CLASS: java2.util2.zip2.ZipOutputStream
- check_rank_length: true
- max_length: 5000
- make_accessible: true
EvoSuite Parameters
- plot: false
- chromosome_length: 40
- static_hack: false
- tournament_size: 10
- max_int: 2048
- string_length: 20
- crossover_rate: 0.75
- max_attempts: 1000
- CP: build/classes
- check_parents_length: true
- PREFIX: java2.util2.zip2
- stopping_condition: MaxStatements
- max_recursion: 10
- primitive_pool: 0.5
- selection_function: Rank
- generations: 2000000
- primitive_reuse_probability: 0.5
- test_excludes: test.excludes
- bloat_factor: 2
- object_reuse_probability: 0.9
- minimize: true
- html: true
- null_probability: 0.1
- strategy: EvoSuite
- elite: 1
- check_best_length: true
- num_tests: 2
- PROJECT_PREFIX: java2.util2.zip2
- OUTPUT_DIR: evosuite-files
- algorithm: SteadyStateGA
- string_replacement: true
- crossover_function: SinglePointRelative
- report_dir: evosuite-report
- test_includes: test.includes
- output_dir: evosuite-files
- criterion: branch
- rank_bias: 1.7
- timeout: 5000
- population: 100
- test_dir: evosuite-tests
- max_size: 100
- check_max_length: true
- TARGET_CLASS: java2.util2.zip2.ZipOutputStream
- check_rank_length: true
- max_length: 5000
- make_accessible: true
Old Parameters
- Algorithm: SteadyStateGA
- Population size: 100
- Initial test length: 40
- Stopping condition: MaxStatements: null
- Bloat control factor: 2
- Random seed: 0
Statistics
- Start time: 2010-10-18 17:11:01
- End time: 2010-10-18 17:15:18
- Fitness evaluations: 268122
- Tests executed: 157146
- Statements executed: 2000002
- Generations: 2682
- Number of tests before minimization: 15
- Number of tests after minimization: 15
- Length of tests before minimization: 136
- Length of tests after minimization: 130
- Total predicates: 55
- Total branches: 110
- Covered branches: 101
- Total methods: 21
- Covered methods: 21
- Methods without branches: 7
- Total coverage goal: 131
- Covered goals: 122
- Time for search: 0:04:16
- Time for minimization: 0:00:00
- Total time: 0:04:17
Test suite
Test case 1
1: String var0 = "q5\u0016\u001F&\u001E";
2: ByteArrayOutputStream var1 = new java.io.ByteArrayOutputStream();
3: ZipOutputStream var2 = new java2.util2.zip2.ZipOutputStream(var1);
4: var2.setComment(var0);
5: ;
6: byte[] var4 = null;
7: var4 = var1.toByteArray();
8: ;
9: byte var5 = -32;
10: try {
11: var2.write(var4, var5, var5);
12: } catch(IndexOutOfBoundsException e) {}
13: ZipEntry var7 = new java2.util2.zip2.ZipEntry(var0);
14: try {
15: var2.putNextEntry(var7);
16: }
17: catch(Class e) {};
18: var7.setComment(var0);
19: ;
20: try {
21: var2.close();
22: }
23: catch(Class e) {};
Test case 2
1: int var0 = 32;
2: ByteArrayOutputStream var1 = new java.io.ByteArrayOutputStream();
3: ZipOutputStream var2 = new java2.util2.zip2.ZipOutputStream(var1);
4: byte[] var3 = new byte[1];
5: try {
6: var2.write(var3, var3[0], var0);
7: } catch(IndexOutOfBoundsException e) {}
8: try {
9: var2.close();
10: } catch(ZipException e) {}
Test case 3
1: ByteArrayOutputStream var0 = new java.io.ByteArrayOutputStream();
2: byte[] var1 = null;
3: var1 = var0.toByteArray();
4: ;
5: ZipOutputStream var2 = new java2.util2.zip2.ZipOutputStream(var0);
6: String var3 = null;
7: var3 = var0.toString();
8: ;
9: ZipEntry var4 = new java2.util2.zip2.ZipEntry(var3);
10: var4.setExtra(var1);
11: ;
12: try {
13: var2.putNextEntry(var4);
14: }
15: catch(Class e) {};
16: try {
17: var2.close();
18: }
19: catch(Class e) {};
20: try {
21: var2.close();
22: }
23: catch(Class e) {};
Test case 4
1: ByteArrayOutputStream var0 = new java.io.ByteArrayOutputStream();
2: ZipOutputStream var1 = new java2.util2.zip2.ZipOutputStream(var0);
3: byte[] var2 = new byte[12];
4: int var3 = -581;
5: try {
6: var1.write(var2, var2[10], var3);
7: } catch(IndexOutOfBoundsException e) {}
Test case 5
1: String var0 = "STORED entry missing size, compressed size, or crc-32";
2: int var1 = null;
3: var1 = java2.util2.zip2.ZipOutputStream.getUTF8Length(var0);
4: ;
Test case 6
1: ByteArrayOutputStream var0 = new java.io.ByteArrayOutputStream();
2: int var1 = 3;
3: var0.write(var1);
4: ;
5: String var3 = null;
6: var3 = var0.toString(var1);
7: ;
8: int var4 = null;
9: var4 = java2.util2.zip2.ZipOutputStream.getUTF8Length(var3);
10: ;
11: ZipOutputStream var5 = new java2.util2.zip2.ZipOutputStream(var0);
12: ZipEntry var6 = new java2.util2.zip2.ZipEntry(var3);
13: try {
14: var5.putNextEntry(var6);
15: }
16: catch(Class e) {};
Test case 7
1: ByteArrayOutputStream var0 = new java.io.ByteArrayOutputStream();
2: int var1 = -22;
3: var0.write(var1);
4: ;
5: String var3 = null;
6: var3 = var0.toString();
7: ;
8: int var4 = null;
9: var4 = java2.util2.zip2.ZipOutputStream.getUTF8Length(var3);
10: ;
Test case 8
1: ByteArrayOutputStream var0 = new java.io.ByteArrayOutputStream();
2: ZipOutputStream var1 = new java2.util2.zip2.ZipOutputStream(var0);
3: String var2 = "[\u0004#";
4: int var3 = 0;
5: var1.setMethod(var3);
6: ;
7: ZipEntry var5 = new java2.util2.zip2.ZipEntry(var2);
8: try {
9: var1.putNextEntry(var5);
10: } catch(ZipException e) {}
Test case 9
1: ByteArrayOutputStream var0 = new java.io.ByteArrayOutputStream();
2: ZipOutputStream var1 = new java2.util2.zip2.ZipOutputStream(var0);
3: String var2 = "\u0000";
4: int var3 = 0;
5: var1.setMethod(var3);
6: ;
7: ZipEntry var5 = new java2.util2.zip2.ZipEntry(var2);
8: var5.setCompressedSize(var3);
9: ;
10: try {
11: var1.putNextEntry(var5);
12: } catch(ZipException e) {}
13: byte[] var8 = new byte[1];
14: try {
15: var1.closeEntry();
16: }
17: catch(Class e) {};
18: try {
19: var1.write(var8);
20: } catch(ZipException e) {}
21: var1.setLevel(var3);
22: ;
23: try {
24: var1.write(var8, var8[0], var8[0]);
25: }
26: catch(Class e) {};
27: try {
28: var1.putNextEntry(var5);
29: } catch(ZipException e) {}
Test case 10
1: ByteArrayOutputStream var0 = new java.io.ByteArrayOutputStream();
2: int var1 = 35;
3: var0.write(var1);
4: ;
5: String var3 = null;
6: var3 = var0.toString(var1);
7: ;
8: byte[] var4 = new byte[14];
9: ZipOutputStream var5 = new java2.util2.zip2.ZipOutputStream(var0);
10: ZipEntry var6 = new java2.util2.zip2.ZipEntry(var3);
11: try {
12: var5.putNextEntry(var6);
13: }
14: catch(Class e) {};
15: var6.setSize(var4[4]);
16: ;
17: var6.setMethod(var4[5]);
18: ;
19: try {
20: var5.close();
21: } catch(ZipException e) {}
22: try {
23: var5.write(var4[7]);
24: } catch(ZipException e) {}
Test case 11
1: ByteArrayOutputStream var0 = new java.io.ByteArrayOutputStream();
2: int var1 = -7;
3: String var2 = null;
4: var2 = var0.toString(var1);
5: ;
6: byte[] var3 = new byte[14];
7: ZipOutputStream var4 = new java2.util2.zip2.ZipOutputStream(var0);
8: ZipEntry var5 = new java2.util2.zip2.ZipEntry(var2);
9: var5.setSize(var3[4]);
10: ;
11: var5.setCrc(var3[9]);
12: ;
13: var5.setMethod(var3[5]);
14: ;
15: try {
16: var4.putNextEntry(var5);
17: }
18: catch(Class e) {};
Test case 12
1: ByteArrayOutputStream var0 = new java.io.ByteArrayOutputStream();
2: String var1 = null;
3: var1 = var0.toString();
4: ;
5: byte[] var2 = new byte[14];
6: ZipOutputStream var3 = new java2.util2.zip2.ZipOutputStream(var0);
7: ZipEntry var4 = new java2.util2.zip2.ZipEntry(var1);
8: try {
9: var3.putNextEntry(var4);
10: }
11: catch(Class e) {};
12: var4.setMethod(var2[5]);
13: ;
14: try {
15: var3.close();
16: } catch(ZipException e) {}
17: String var8 = null;
18: var8 = var4.getComment();
19: ;
20: var3.setComment(var8);
21: ;
Test case 13
1: int var0 = 8;
2: ByteArrayOutputStream var1 = new java.io.ByteArrayOutputStream(var0);
3: DeflaterOutputStream var2 = new java2.util2.zip2.DeflaterOutputStream(var1);
4: ZipOutputStream var3 = new java2.util2.zip2.ZipOutputStream(var2);
5: int var4 = 15;
6: try {
7: var3.setMethod(var4);
8: } catch(IllegalArgumentException e) {}
9: var3.setMethod(var0);
10: ;
Test case 14
1: ByteArrayOutputStream var0 = new java.io.ByteArrayOutputStream();
2: ZipOutputStream var1 = new java2.util2.zip2.ZipOutputStream(var0);
3: String var2 = "A\u001B_\u0001\u0001_\u0014TE\u0012\u000F72";
4: ZipEntry var3 = new java2.util2.zip2.ZipEntry(var2);
5: long var4 = 4L;
6: var3.setSize(var4);
7: ;
8: try {
9: var1.putNextEntry(var3);
10: }
11: catch(Class e) {};
12: try {
13: var1.putNextEntry(var3);
14: } catch(ZipException e) {}
15: ZipOutputStream var8 = new java2.util2.zip2.ZipOutputStream(var0);
16: try {
17: var8.putNextEntry(var3);
18: }
19: catch(Class e) {};
20: try {
21: var8.finish();
22: }
23: catch(Class e) {};
Test case 15
1: ByteArrayOutputStream var0 = new java.io.ByteArrayOutputStream();
2: ZipOutputStream var1 = new java2.util2.zip2.ZipOutputStream(var0);
3: String var2 = "A\u001B_\u0001\u0001_\u0014TE\u0012<72";
4: ZipEntry var3 = new java2.util2.zip2.ZipEntry(var2);
5: try {
6: var1.putNextEntry(var3);
7: }
8: catch(Class e) {};
9: try {
10: var1.finish();
11: }
12: catch(Class e) {};
13: long var6 = 1394L;
14: var3.setCrc(var6);
15: ;
16: try {
17: var1.close();
18: }
19: catch(Class e) {};
20: try {
21: var1.finish();
22: } catch(IOException e) {}
23: ZipOutputStream var10 = new java2.util2.zip2.ZipOutputStream(var0);
24: try {
25: var10.putNextEntry(var3);
26: }
27: catch(Class e) {};
28: try {
29: var10.closeEntry();
30: } catch(ZipException e) {}
Source Code
1: /*
2: * @(#)ZipOutputStream.java 1.36 10/03/23
3: *
4: * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
5: * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6: */
7:
8: package java2.util2.zip2;
9:
10: import java.io.OutputStream;
11: import java.io.IOException;
12: import java.util.Vector;
13: import java.util.HashSet;
14:
15: import java.util.zip.ZipException;
16: import java.util.zip.Deflater;
17: import java.util.zip.CRC32;
18:
19: /**
20: * This class implements an output stream filter for writing files in the
21: * ZIP file format. Includes support for both compressed and uncompressed
22: * entries.
23: *
24: * @author David Connelly
25: * @version 1.36, 03/23/10
26: */
27: public
28: class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
29:
30: private static class XEntry {
31: public final ZipEntry entry;
32: public final long offset;
33: public final int flag;
34: public XEntry(ZipEntry entry, long offset) {
35: this.entry = entry;
36: this.offset = offset;
37: this.flag = (entry.method == DEFLATED &&
38: (entry.size == -1 ||
39: entry.csize == -1 ||
40: entry.crc == -1))
41: // store size, compressed size, and crc-32 in data descriptor
42: // immediately following the compressed entry data
43: ? 8
44: // store size, compressed size, and crc-32 in LOC header
45: : 0;
46: }
47: }
48:
49: private XEntry current;
50: private Vector<XEntry> xentries = new Vector<XEntry>();
51: private HashSet<String> names = new HashSet<String>();
52: private CRC32 crc = new CRC32();
53: private long written = 0;
54: private long locoff = 0;
55: private String comment;
56: private int method = DEFLATED;
57: private boolean finished;
58:
59: private boolean closed = false;
60:
61: private static int version(ZipEntry e) throws ZipException {
62: switch (e.method) {
63: case DEFLATED: return 20;
64: case STORED: return 10;
65: default: throw new ZipException("unsupported compression method");
66: }
67: }
68:
69: /**
70: * Checks to make sure that this stream has not been closed.
71: */
72: private void ensureOpen() throws IOException {
73: if (closed) {
74: throw new IOException("Stream closed");
75: }
76: }
77: /**
78: * Compression method for uncompressed (STORED) entries.
79: */
80: public static final int STORED = ZipEntry.STORED;
81:
82: /**
83: * Compression method for compressed (DEFLATED) entries.
84: */
85: public static final int DEFLATED = ZipEntry.DEFLATED;
86:
87: /**
88: * Creates a new ZIP output stream.
89: * @param out the actual output stream
90: */
91: public ZipOutputStream(OutputStream out) {
92: super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
93: usesDefaultDeflater = true;
94: }
95:
96: /**
97: * Sets the ZIP file comment.
98: * @param comment the comment string
99: * @exception IllegalArgumentException if the length of the specified
100: * ZIP file comment is greater than 0xFFFF bytes
101: */
102: public void setComment(String comment) {
103: if (comment != null && comment.length() > 0xffff/3
104: && getUTF8Length(comment) > 0xffff) {
105: throw new IllegalArgumentException("ZIP file comment too long.");
106: }
107: this.comment = comment;
108: }
109:
110: /**
111: * Sets the default compression method for subsequent entries. This
112: * default will be used whenever the compression method is not specified
113: * for an individual ZIP file entry, and is initially set to DEFLATED.
114: * @param method the default compression method
115: * @exception IllegalArgumentException if the specified compression method
116: * is invalid
117: */
118: public void setMethod(int method) {
119: if (method != DEFLATED && method != STORED) {
120: throw new IllegalArgumentException("invalid compression method");
121: }
122: this.method = method;
123: }
124:
125: /**
126: * Sets the compression level for subsequent entries which are DEFLATED.
127: * The default setting is DEFAULT_COMPRESSION.
128: * @param level the compression level (0-9)
129: * @exception IllegalArgumentException if the compression level is invalid
130: */
131: public void setLevel(int level) {
132: def.setLevel(level);
133: }
134:
135: /**
136: * Begins writing a new ZIP file entry and positions the stream to the
137: * start of the entry data. Closes the current entry if still active.
138: * The default compression method will be used if no compression method
139: * was specified for the entry, and the current time will be used if
140: * the entry has no set modification time.
141: * @param e the ZIP entry to be written
142: * @exception ZipException if a ZIP format error has occurred
143: * @exception IOException if an I/O error has occurred
144: */
145: public void putNextEntry(ZipEntry e) throws IOException {
146: ensureOpen();
147: if (current != null) {
148: closeEntry(); // close previous entry
149: }
150: if (e.time == -1) {
151: e.setTime(System.currentTimeMillis());
152: }
153: if (e.method == -1) {
154: e.method = method; // use default method
155: }
156: switch (e.method) {
157: case DEFLATED:
158: break;
159: case STORED:
160: // compressed size, uncompressed size, and crc-32 must all be
161: // set for entries using STORED compression method
162: if (e.size == -1) {
163: e.size = e.csize;
164: } else if (e.csize == -1) {
165: e.csize = e.size;
166: } else if (e.size != e.csize) {
167: throw new ZipException(
168: "STORED entry where compressed != uncompressed size");
169: }
170: if (e.size == -1 || e.crc == -1) {
171: throw new ZipException(
172: "STORED entry missing size, compressed size, or crc-32");
173: }
174: break;
175: default:
176: throw new ZipException("unsupported compression method");
177: }
178: if (! names.add(e.name)) {
179: throw new ZipException("duplicate entry: " + e.name);
180: }
181: current = new XEntry(e, written);
182: xentries.add(current);
183: writeLOC(current);
184: }
185:
186: /**
187: * Closes the current ZIP entry and positions the stream for writing
188: * the next entry.
189: * @exception ZipException if a ZIP format error has occurred
190: * @exception IOException if an I/O error has occurred
191: */
192: public void closeEntry() throws IOException {
193: ensureOpen();
194: if (current != null) {
195: ZipEntry e = current.entry;
196: switch (e.method) {
197: case DEFLATED:
198: def.finish();
199: while (!def.finished()) {
200: deflate();
201: }
202: if ((current.flag & 8) == 0) {
203: // verify size, compressed size, and crc-32 settings
204: if (e.size != def.getBytesRead()) {
205: throw new ZipException(
206: "invalid entry size (expected " + e.size +
207: " but got " + def.getBytesRead() + " bytes)");
208: }
209: if (e.csize != def.getBytesWritten()) {
210: throw new ZipException(
211: "invalid entry compressed size (expected " +
212: e.csize + " but got " + def.getBytesWritten() + " bytes)");
213: }
214: if (e.crc != crc.getValue()) {
215: throw new ZipException(
216: "invalid entry CRC-32 (expected 0x" +
217: Long.toHexString(e.crc) + " but got 0x" +
218: Long.toHexString(crc.getValue()) + ")");
219: }
220: } else {
221: e.size = def.getBytesRead();
222: e.csize = def.getBytesWritten();
223: e.crc = crc.getValue();
224: writeEXT(e);
225: }
226: def.reset();
227: written += e.csize;
228: break;
229: case STORED:
230: // we already know that both e.size and e.csize are the same
231: if (e.size != written - locoff) {
232: throw new ZipException(
233: "invalid entry size (expected " + e.size +
234: " but got " + (written - locoff) + " bytes)");
235: }
236: if (e.crc != crc.getValue()) {
237: throw new ZipException(
238: "invalid entry crc-32 (expected 0x" +
239: Long.toHexString(e.crc) + " but got 0x" +
240: Long.toHexString(crc.getValue()) + ")");
241: }
242: break;
243: default:
244: throw new ZipException("invalid compression method");
245: }
246: crc.reset();
247: current = null;
248: }
249: }
250:
251: /**
252: * Writes an array of bytes to the current ZIP entry data. This method
253: * will block until all the bytes are written.
254: * @param b the data to be written
255: * @param off the start offset in the data
256: * @param len the number of bytes that are written
257: * @exception ZipException if a ZIP file error has occurred
258: * @exception IOException if an I/O error has occurred
259: */
260: public synchronized void write(byte[] b, int off, int len)
261: throws IOException
262: {
263: ensureOpen();
264: if (off < 0 || len < 0 || off > b.length - len) {
265: throw new IndexOutOfBoundsException();
266: } else if (len == 0) {
267: return;
268: }
269:
270: if (current == null) {
271: throw new ZipException("no current ZIP entry");
272: }
273: ZipEntry entry = current.entry;
274: switch (entry.method) {
275: case DEFLATED:
276: super.write(b, off, len);
277: break;
278: case STORED:
279: written += len;
280: if (written - locoff > entry.size) {
281: throw new ZipException(
282: "attempt to write past end of STORED entry");
283: }
284: out.write(b, off, len);
285: break;
286: default:
287: throw new ZipException("invalid compression method");
288: }
289: crc.update(b, off, len);
290: }
291:
292: /**
293: * Finishes writing the contents of the ZIP output stream without closing
294: * the underlying stream. Use this method when applying multiple filters
295: * in succession to the same output stream.
296: * @exception ZipException if a ZIP file error has occurred
297: * @exception IOException if an I/O exception has occurred
298: */
299: public void finish() throws IOException {
300: ensureOpen();
301: if (finished) {
302: return;
303: }
304: if (current != null) {
305: closeEntry();
306: }
307: if (xentries.size() < 1) {
308: throw new ZipException("ZIP file must have at least one entry");
309: }
310: // write central directory
311: long off = written;
312: for (XEntry xentry : xentries)
313: writeCEN(xentry);
314: writeEND(off, written - off);
315: finished = true;
316: }
317:
318: /**
319: * Closes the ZIP output stream as well as the stream being filtered.
320: * @exception ZipException if a ZIP file error has occurred
321: * @exception IOException if an I/O error has occurred
322: */
323: public void close() throws IOException {
324: if (!closed) {
325: super.close();
326: closed = true;
327: }
328: }
329:
330: /*
331: * Writes local file (LOC) header for specified entry.
332: */
333: private void writeLOC(XEntry xentry) throws IOException {
334: ZipEntry e = xentry.entry;
335: int flag = xentry.flag;
336: writeInt(LOCSIG); // LOC header signature
337: writeShort(version(e)); // version needed to extract
338: writeShort(flag); // general purpose bit flag
339: writeShort(e.method); // compression method
340: writeInt(e.time); // last modification time
341: if ((flag & 8) == 8) {
342: // store size, uncompressed size, and crc-32 in data descriptor
343: // immediately following compressed entry data
344: writeInt(0);
345: writeInt(0);
346: writeInt(0);
347: } else {
348: writeInt(e.crc); // crc-32
349: writeInt(e.csize); // compressed size
350: writeInt(e.size); // uncompressed size
351: }
352: byte[] nameBytes = getUTF8Bytes(e.name);
353: writeShort(nameBytes.length);
354: writeShort(e.extra != null ? e.extra.length : 0);
355: writeBytes(nameBytes, 0, nameBytes.length);
356: if (e.extra != null) {
357: writeBytes(e.extra, 0, e.extra.length);
358: }
359: locoff = written;
360: }
361:
362: /*
363: * Writes extra data descriptor (EXT) for specified entry.
364: */
365: private void writeEXT(ZipEntry e) throws IOException {
366: writeInt(EXTSIG); // EXT header signature
367: writeInt(e.crc); // crc-32
368: writeInt(e.csize); // compressed size
369: writeInt(e.size); // uncompressed size
370: }
371:
372: /*
373: * Write central directory (CEN) header for specified entry.
374: * REMIND: add support for file attributes
375: */
376: private void writeCEN(XEntry xentry) throws IOException {
377: ZipEntry e = xentry.entry;
378: int flag = xentry.flag;
379: int version = version(e);
380: writeInt(CENSIG); // CEN header signature
381: writeShort(version); // version made by
382: writeShort(version); // version needed to extract
383: writeShort(flag); // general purpose bit flag
384: writeShort(e.method); // compression method
385: writeInt(e.time); // last modification time
386: writeInt(e.crc); // crc-32
387: writeInt(e.csize); // compressed size
388: writeInt(e.size); // uncompressed size
389: byte[] nameBytes = getUTF8Bytes(e.name);
390: writeShort(nameBytes.length);
391: writeShort(e.extra != null ? e.extra.length : 0);
392: byte[] commentBytes;
393: if (e.comment != null) {
394: commentBytes = getUTF8Bytes(e.comment);
395: writeShort(commentBytes.length);
396: } else {
397: commentBytes = null;
398: writeShort(0);
399: }
400: writeShort(0); // starting disk number
401: writeShort(0); // internal file attributes (unused)
402: writeInt(0); // external file attributes (unused)
403: writeInt(xentry.offset); // relative offset of local header
404: writeBytes(nameBytes, 0, nameBytes.length);
405: if (e.extra != null) {
406: writeBytes(e.extra, 0, e.extra.length);
407: }
408: if (commentBytes != null) {
409: writeBytes(commentBytes, 0, commentBytes.length);
410: }
411: }
412:
413: /*
414: * Writes end of central directory (END) header.
415: */
416: private void writeEND(long off, long len) throws IOException {
417: int count = xentries.size();
418: writeInt(ENDSIG); // END record signature
419: writeShort(0); // number of this disk
420: writeShort(0); // central directory start disk
421: writeShort(count); // number of directory entries on disk
422: writeShort(count); // total number of directory entries
423: writeInt(len); // length of central directory
424: writeInt(off); // offset of central directory
425: if (comment != null) { // zip file comment
426: byte[] b = getUTF8Bytes(comment);
427: writeShort(b.length);
428: writeBytes(b, 0, b.length);
429: } else {
430: writeShort(0);
431: }
432: }
433:
434: /*
435: * Writes a 16-bit short to the output stream in little-endian byte order.
436: */
437: private void writeShort(int v) throws IOException {
438: OutputStream out = this.out;
439: out.write((v >>> 0) & 0xff);
440: out.write((v >>> 8) & 0xff);
441: written += 2;
442: }
443:
444: /*
445: * Writes a 32-bit int to the output stream in little-endian byte order.
446: */
447: private void writeInt(long v) throws IOException {
448: OutputStream out = this.out;
449: out.write((int)((v >>> 0) & 0xff));
450: out.write((int)((v >>> 8) & 0xff));
451: out.write((int)((v >>> 16) & 0xff));
452: out.write((int)((v >>> 24) & 0xff));
453: written += 4;
454: }
455:
456: /*
457: * Writes an array of bytes to the output stream.
458: */
459: private void writeBytes(byte[] b, int off, int len) throws IOException {
460: super.out.write(b, off, len);
461: written += len;
462: }
463:
464: /*
465: * Returns the length of String's UTF8 encoding.
466: */
467: static int getUTF8Length(String s) {
468: int count = 0;
469: for (int i = 0; i < s.length(); i++) {
470: char ch = s.charAt(i);
471: if (ch <= 0x7f) {
472: count++;
473: } else if (ch <= 0x7ff) {
474: count += 2;
475: } else {
476: count += 3;
477: }
478: }
479: return count;
480: }
481:
482: /*
483: * Returns an array of bytes representing the UTF8 encoding
484: * of the specified String.
485: */
486: private static byte[] getUTF8Bytes(String s) {
487: char[] c = s.toCharArray();
488: int len = c.length;
489: // Count the number of encoded bytes...
490: int count = 0;
491: for (int i = 0; i < len; i++) {
492: int ch = c[i];
493: if (ch <= 0x7f) {
494: count++;
495: } else if (ch <= 0x7ff) {
496: count += 2;
497: } else {
498: count += 3;
499: }
500: }
501: // Now return the encoded bytes...
502: byte[] b = new byte[count];
503: int off = 0;
504: for (int i = 0; i < len; i++) {
505: int ch = c[i];
506: if (ch <= 0x7f) {
507: b[off++] = (byte)ch;
508: } else if (ch <= 0x7ff) {
509: b[off++] = (byte)((ch >> 6) | 0xc0);
510: b[off++] = (byte)((ch & 0x3f) | 0x80);
511: } else {
512: b[off++] = (byte)((ch >> 12) | 0xe0);
513: b[off++] = (byte)(((ch >> 6) & 0x3f) | 0x80);
514: b[off++] = (byte)((ch & 0x3f) | 0x80);
515: }
516: }
517: return b;
518: }
519: }