- Timestamp:
- Apr 27, 2004, 8:39:34 PM (22 years ago)
- Location:
- branches/GNU/src/gcc
- Files:
-
- 2 edited
-
. (modified) (1 prop)
-
libjava/java/util/zip/ZipOutputStream.java (modified) (3 diffs, 1 prop)
Legend:
- Unmodified
- Added
- Removed
-
branches/GNU/src/gcc
- Property svn:ignore
-
old new 26 26 configure.vr 27 27 configure.vrs 28 28 29 Makefile 29 dir.info30 30 lost+found 31 31 update.out
-
- Property svn:ignore
-
branches/GNU/src/gcc/libjava/java/util/zip/ZipOutputStream.java
-
Property cvs2svn:cvs-rev
changed from
1.1to1.1.1.2
r1390 r1391 1 /* ZipOutputStream.java - Create a file in zip format2 Copyright (C) 1999, 2000Free Software Foundation, Inc.1 /* 2 Copyright (C) Free Software Foundation, Inc. 3 3 4 4 This file is part of GNU Classpath. … … 8 8 the Free Software Foundation; either version 2, or (at your option) 9 9 any later version. 10 10 11 11 GNU Classpath is distributed in the hope that it will be useful, but 12 12 WITHOUT ANY WARRANTY; without even the implied warranty of … … 37 37 38 38 package java.util.zip; 39 40 import java.io.*; 41 42 /* Written using on-line Java Platform 1.2 API Specification 43 * and JCL book. 44 * Believed complete and correct. 39 import java.io.OutputStream; 40 import java.io.IOException; 41 import java.io.UnsupportedEncodingException; 42 import java.util.Vector; 43 import java.util.Enumeration; 44 45 /** 46 * This is a FilterOutputStream that writes the files into a zip 47 * archive one after another. It has a special method to start a new 48 * zip entry. The zip entries contains information about the file name 49 * size, compressed size, CRC, etc. 50 * 51 * It includes support for STORED and DEFLATED entries. 52 * 53 * This class is not thread safe. 54 * 55 * @author Jochen Hoenicke 45 56 */ 46 47 public class ZipOutputStream extends DeflaterOutputStream 48 implements ZipConstants 57 public class ZipOutputStream extends DeflaterOutputStream implements ZipConstants 49 58 { 50 public static final int STORED = 0; 51 public static final int DEFLATED = 8; 52 53 public void close () throws IOException 54 { 55 finish (); 56 out.close(); 57 } 58 59 public void closeEntry () throws IOException 60 { 61 int compressed_size; 62 if (current.method == STORED) 63 { 64 compressed_size = uncompressed_size; 59 private Vector entries = new Vector(); 60 private CRC32 crc = new CRC32(); 61 private ZipEntry curEntry = null; 62 63 private int curMethod; 64 private int size; 65 private int offset = 0; 66 67 private byte[] zipComment = new byte[0]; 68 private int defaultMethod = DEFLATED; 69 70 /** 71 * Our Zip version is hard coded to 1.0 resp. 2.0 72 */ 73 private final static int ZIP_STORED_VERSION = 10; 74 private final static int ZIP_DEFLATED_VERSION = 20; 75 76 /** 77 * Compression method. This method doesn't compress at all. 78 */ 79 public final static int STORED = 0; 80 /** 81 * Compression method. This method uses the Deflater. 82 */ 83 public final static int DEFLATED = 8; 84 85 /** 86 * Creates a new Zip output stream, writing a zip archive. 87 * @param out the output stream to which the zip archive is written. 88 */ 89 public ZipOutputStream(OutputStream out) 90 { 91 super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true)); 92 } 93 94 /** 95 * Set the zip file comment. 96 * @param comment the comment. 97 * @exception IllegalArgumentException if encoding of comment is 98 * longer than 0xffff bytes. 99 */ 100 public void setComment(String comment) 101 { 102 byte[] commentBytes; 103 commentBytes = comment.getBytes(); 104 if (commentBytes.length > 0xffff) 105 throw new IllegalArgumentException("Comment too long."); 106 zipComment = commentBytes; 107 } 108 109 /** 110 * Sets default compression method. If the Zip entry specifies 111 * another method its method takes precedence. 112 * @param method the method. 113 * @exception IllegalArgumentException if method is not supported. 114 * @see #STORED 115 * @see #DEFLATED 116 */ 117 public void setMethod(int method) 118 { 119 if (method != STORED && method != DEFLATED) 120 throw new IllegalArgumentException("Method not supported."); 121 defaultMethod = method; 122 } 123 124 /** 125 * Sets default compression level. The new level will be activated 126 * immediately. 127 * @exception IllegalArgumentException if level is not supported. 128 * @see Deflater 129 */ 130 public void setLevel(int level) 131 { 132 def.setLevel(level); 133 } 134 135 /** 136 * Write an unsigned short in little endian byte order. 137 */ 138 private final void writeLeShort(int value) throws IOException 139 { 140 out.write(value & 0xff); 141 out.write((value >> 8) & 0xff); 142 } 143 144 /** 145 * Write an int in little endian byte order. 146 */ 147 private final void writeLeInt(int value) throws IOException 148 { 149 writeLeShort(value); 150 writeLeShort(value >> 16); 151 } 152 153 /** 154 * Starts a new Zip entry. It automatically closes the previous 155 * entry if present. If the compression method is stored, the entry 156 * must have a valid size and crc, otherwise all elements (except 157 * name) are optional, but must be correct if present. If the time 158 * is not set in the entry, the current time is used. 159 * @param entry the entry. 160 * @exception IOException if an I/O error occured. 161 * @exception ZipException if stream was finished. 162 */ 163 public void putNextEntry(ZipEntry entry) throws IOException 164 { 165 if (entries == null) 166 throw new ZipException("ZipOutputStream was finished"); 167 168 int method = entry.getMethod(); 169 int flags = 0; 170 if (method == -1) 171 method = defaultMethod; 172 173 if (method == STORED) 174 { 175 if (entry.getCompressedSize() >= 0) 176 { 177 if (entry.getSize() < 0) 178 entry.setSize(entry.getCompressedSize()); 179 else if (entry.getSize() != entry.getCompressedSize()) 180 throw new ZipException 181 ("Method STORED, but compressed size != size"); 182 } 183 else 184 entry.setCompressedSize(entry.getSize()); 185 186 if (entry.getSize() < 0) 187 throw new ZipException("Method STORED, but size not set"); 188 if (entry.getCrc() < 0) 189 throw new ZipException("Method STORED, but crc not set"); 190 } 191 else if (method == DEFLATED) 192 { 193 if (entry.getCompressedSize() < 0 194 || entry.getSize() < 0 || entry.getCrc() < 0) 195 flags |= 8; 196 } 197 198 if (curEntry != null) 199 closeEntry(); 200 201 if (entry.getTime() < 0) 202 entry.setTime(System.currentTimeMillis()); 203 204 entry.flags = flags; 205 entry.offset = offset; 206 entry.setMethod(method); 207 curMethod = method; 208 /* Write the local file header */ 209 writeLeInt(LOCSIG); 210 writeLeShort(method == STORED 211 ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION); 212 writeLeShort(flags); 213 writeLeShort(method); 214 writeLeInt(entry.getDOSTime()); 215 if ((flags & 8) == 0) 216 { 217 writeLeInt((int)entry.getCrc()); 218 writeLeInt((int)entry.getCompressedSize()); 219 writeLeInt((int)entry.getSize()); 65 220 } 66 221 else 67 222 { 68 super.finish(); 69 compressed_size = def.getTotalOut(); 70 } 71 long crc = sum.getValue(); 72 73 bytes_written += compressed_size; 74 75 if (current.getCrc() == -1 || current.getCompressedSize() == -1 76 || current.getSize() == -1) 77 { 78 current.setCrc(crc); 79 current.compressedSize = compressed_size; 80 current.setSize(uncompressed_size); 81 put4 (0x08074b50); 82 put4 ((int) (current.getCrc())); 83 put4 ((int) (current.getCompressedSize())); 84 put4 ((int) (current.getSize())); 85 bytes_written += 16; 86 } 87 else if (current.getCrc() != crc 88 || current.getCompressedSize() != compressed_size 89 || current.getSize() != uncompressed_size) 90 throw new ZipException ("zip entry field incorrect"); 91 92 current.next = chain; 93 chain = current; 94 current = null; 95 } 96 97 public void write (int bval) throws IOException 98 { 99 if (current.method == STORED) 100 { 101 out.write(bval); 102 } 103 else 104 super.write(bval); 105 sum.update(bval); 106 uncompressed_size += 1; 107 } 108 109 public void write (byte[] buf, int off, int len) throws IOException 110 { 111 if (current.method == STORED) 112 out.write(buf, off, len); 113 else 114 super.write(buf, off, len); 115 sum.update(buf, off, len); 116 uncompressed_size += len; 117 } 118 119 public void finish () throws IOException 120 { 121 if (current != null) 122 closeEntry (); 123 124 // Write the central directory. 125 long offset = bytes_written; 126 int count = 0; 127 int bytes = 0; 128 while (chain != null) 129 { 130 bytes += write_entry (chain, false); 131 ++count; 132 chain = chain.next; 133 } 134 135 // Write the end of the central directory record. 136 put4 (0x06054b50); 137 // Disk number. 138 put2 (0); 139 // Another disk number. 140 put2 (0); 141 put2 (count); 142 put2 (count); 143 put4 (bytes); 144 put4 ((int) offset); 145 146 byte[] c = comment.getBytes("8859_1"); 147 put2 (c.length); 148 out.write(c); 149 } 150 151 // Helper for finish and putNextEntry. 152 private int write_entry (ZipEntry entry, boolean is_local) 153 throws IOException 154 { 155 int bytes = put4 (is_local ? 0x04034b50 : 0x02014b50); 156 if (! is_local) 157 bytes += put_version (); 158 bytes += put_version (); 159 160 boolean crc_after = false; 161 if (is_local 162 && (entry.getCrc() == -1 || entry.getCompressedSize() == -1 163 || entry.getSize() == -1)) 164 crc_after = true; 165 // For the bits field we always indicate `normal' compression, 166 // even if that isn't true. 167 bytes += put2 (crc_after ? (1 << 3) : 0); 168 bytes += put2 (entry.method); 169 170 bytes += put2(0); // time - FIXME 171 bytes += put2(0); // date - FIXME 172 173 if (crc_after) 174 { 175 // CRC, compressedSize, and Size are always 0 in this header. 176 // The actual values are given after the entry. 177 bytes += put4 (0); 178 bytes += put4 (0); 179 bytes += put4 (0); 180 } 181 else 182 { 183 bytes += put4 ((int) (entry.getCrc())); 184 bytes += put4 ((int) (entry.getCompressedSize())); 185 bytes += put4 ((int) (entry.getSize())); 186 } 187 188 byte[] name = entry.name.getBytes("8859_1"); 189 bytes += put2 (name.length); 190 bytes += put2 (entry.extra == null ? 0 : entry.extra.length); 191 192 byte[] comment = null; 193 if (! is_local) 194 { 195 if (entry.getComment() == null) 196 bytes += put2 (0); 197 else 198 { 199 comment = entry.getComment().getBytes("8859_1"); 200 bytes += put2 (comment.length); 201 } 202 203 // Disk number start. 204 bytes += put2 (0); 205 // Internal file attributes. 206 bytes += put2 (0); 207 // External file attributes. 208 bytes += put4 (0); 209 // Relative offset of local header. 210 bytes += put4 ((int) entry.relativeOffset); 211 } 212 213 out.write (name); 214 bytes += name.length; 215 if (entry.extra != null) 216 { 217 out.write(entry.extra); 218 bytes += entry.extra.length; 219 } 220 if (comment != null) 221 { 223 writeLeInt(0); 224 writeLeInt(0); 225 writeLeInt(0); 226 } 227 byte[] name = entry.getName().getBytes(); 228 if (name.length > 0xffff) 229 throw new ZipException("Name too long."); 230 byte[] extra = entry.getExtra(); 231 if (extra == null) 232 extra = new byte[0]; 233 writeLeShort(name.length); 234 writeLeShort(extra.length); 235 out.write(name); 236 out.write(extra); 237 238 offset += LOCHDR + name.length + extra.length; 239 240 /* Activate the entry. */ 241 242 curEntry = entry; 243 crc.reset(); 244 if (method == DEFLATED) 245 def.reset(); 246 size = 0; 247 } 248 249 /** 250 * Closes the current entry. 251 * @exception IOException if an I/O error occured. 252 * @exception ZipException if no entry is active. 253 */ 254 public void closeEntry() throws IOException 255 { 256 if (curEntry == null) 257 throw new ZipException("No open entry"); 258 259 /* First finish the deflater, if appropriate */ 260 if (curMethod == DEFLATED) 261 super.finish(); 262 263 int csize = curMethod == DEFLATED ? def.getTotalOut() : size; 264 265 if (curEntry.getSize() < 0) 266 curEntry.setSize(size); 267 else if (curEntry.getSize() != size) 268 throw new ZipException("size was "+size 269 +", but I expected "+curEntry.getSize()); 270 271 if (curEntry.getCompressedSize() < 0) 272 curEntry.setCompressedSize(csize); 273 else if (curEntry.getCompressedSize() != csize) 274 throw new ZipException("compressed size was "+csize 275 +", but I expected "+curEntry.getSize()); 276 277 if (curEntry.getCrc() < 0) 278 curEntry.setCrc(crc.getValue()); 279 else if (curEntry.getCrc() != crc.getValue()) 280 throw new ZipException("crc was " + Long.toHexString(crc.getValue()) 281 + ", but I expected " 282 + Long.toHexString(curEntry.getCrc())); 283 284 offset += csize; 285 286 /* Now write the data descriptor entry if needed. */ 287 if (curMethod == DEFLATED && (curEntry.flags & 8) != 0) 288 { 289 writeLeInt(EXTSIG); 290 writeLeInt((int)curEntry.getCrc()); 291 writeLeInt((int)curEntry.getCompressedSize()); 292 writeLeInt((int)curEntry.getSize()); 293 offset += EXTHDR; 294 } 295 296 entries.addElement(curEntry); 297 curEntry = null; 298 } 299 300 /** 301 * Writes the given buffer to the current entry. 302 * @exception IOException if an I/O error occured. 303 * @exception ZipException if no entry is active. 304 */ 305 public void write(byte[] b, int off, int len) throws IOException 306 { 307 if (curEntry == null) 308 throw new ZipException("No open entry."); 309 310 switch (curMethod) 311 { 312 case DEFLATED: 313 super.write(b, off, len); 314 break; 315 316 case STORED: 317 out.write(b, off, len); 318 break; 319 } 320 321 crc.update(b, off, len); 322 size += len; 323 } 324 325 /** 326 * Finishes the stream. This will write the central directory at the 327 * end of the zip file and flush the stream. 328 * @exception IOException if an I/O error occured. 329 */ 330 public void finish() throws IOException 331 { 332 if (entries == null) 333 return; 334 if (curEntry != null) 335 closeEntry(); 336 337 int numEntries = 0; 338 int sizeEntries = 0; 339 340 Enumeration enum = entries.elements(); 341 while (enum.hasMoreElements()) 342 { 343 ZipEntry entry = (ZipEntry) enum.nextElement(); 344 345 int method = entry.getMethod(); 346 writeLeInt(CENSIG); 347 writeLeShort(method == STORED 348 ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION); 349 writeLeShort(method == STORED 350 ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION); 351 writeLeShort(entry.flags); 352 writeLeShort(method); 353 writeLeInt(entry.getDOSTime()); 354 writeLeInt((int)entry.getCrc()); 355 writeLeInt((int)entry.getCompressedSize()); 356 writeLeInt((int)entry.getSize()); 357 358 byte[] name = entry.getName().getBytes(); 359 if (name.length > 0xffff) 360 throw new ZipException("Name too long."); 361 byte[] extra = entry.getExtra(); 362 if (extra == null) 363 extra = new byte[0]; 364 String strComment = entry.getComment(); 365 byte[] comment = strComment != null 366 ? strComment.getBytes() : new byte[0]; 367 if (comment.length > 0xffff) 368 throw new ZipException("Comment too long."); 369 370 writeLeShort(name.length); 371 writeLeShort(extra.length); 372 writeLeShort(comment.length); 373 writeLeShort(0); /* disk number */ 374 writeLeShort(0); /* internal file attr */ 375 writeLeInt(0); /* external file attr */ 376 writeLeInt(entry.offset); 377 378 out.write(name); 379 out.write(extra); 222 380 out.write(comment); 223 bytes += comment.length; 224 } 225 226 bytes_written += bytes; 227 return bytes; 228 } 229 230 public void putNextEntry (ZipEntry entry) throws IOException 231 { 232 if (current != null) 233 closeEntry (); 234 235 if (entry.method < 0 ) 236 entry.method = method; 237 if (entry.method == STORED) 238 { 239 if (entry.getSize() == -1 || entry.getCrc() == -1) 240 throw new ZipException ("required entry not set"); 241 // Just in case. 242 entry.compressedSize = entry.getSize(); 243 } 244 entry.relativeOffset = bytes_written; 245 write_entry (entry, true); 246 current = entry; 247 int compr = (method == STORED) ? Deflater.NO_COMPRESSION : level; 248 def.reset(); 249 def.setLevel(compr); 250 sum.reset(); 251 uncompressed_size = 0; 252 } 253 254 public void setLevel (int level) 255 { 256 if (level != Deflater.DEFAULT_COMPRESSION 257 && (level < Deflater.NO_COMPRESSION 258 || level > Deflater.BEST_COMPRESSION)) 259 throw new IllegalArgumentException (); 260 this.level = level; 261 } 262 263 public void setMethod (int method) 264 { 265 if (method != DEFLATED && method != STORED) 266 throw new IllegalArgumentException (); 267 this.method = method; 268 } 269 270 public void setComment (String comment) 271 { 272 if (comment.length() > 65535) 273 throw new IllegalArgumentException (); 274 this.comment = comment; 275 } 276 277 public ZipOutputStream (OutputStream out) 278 { 279 super (out, new Deflater (Deflater.DEFAULT_COMPRESSION, true), 8192); 280 sum = new CRC32 (); 281 } 282 283 private int put2 (int i) throws IOException 284 { 285 out.write (i); 286 out.write (i >> 8); 287 return 2; 288 } 289 290 private int put4 (int i) throws IOException 291 { 292 out.write (i); 293 out.write (i >> 8); 294 out.write (i >> 16); 295 out.write (i >> 24); 296 return 4; 297 } 298 299 private int put_version () throws IOException 300 { 301 // FIXME: for now we assume Unix, and we ignore the version 302 // number. 303 return put2 (3 << 8); 304 } 305 306 // The entry we are currently writing, or null if we've called 307 // closeEntry. 308 private ZipEntry current; 309 // The chain of entries which have been written to this file. 310 private ZipEntry chain; 311 312 private int method = DEFLATED; 313 private int level = Deflater.DEFAULT_COMPRESSION; 314 private String comment = ""; 315 private long bytes_written; 316 317 private int uncompressed_size; 318 319 /** The checksum object. */ 320 private Checksum sum; 381 numEntries++; 382 sizeEntries += CENHDR + name.length + extra.length + comment.length; 383 } 384 385 writeLeInt(ENDSIG); 386 writeLeShort(0); /* disk number */ 387 writeLeShort(0); /* disk with start of central dir */ 388 writeLeShort(numEntries); 389 writeLeShort(numEntries); 390 writeLeInt(sizeEntries); 391 writeLeInt(offset); 392 writeLeShort(zipComment.length); 393 out.write(zipComment); 394 out.flush(); 395 entries = null; 396 } 321 397 } -
Property cvs2svn:cvs-rev
changed from
Note:
See TracChangeset
for help on using the changeset viewer.
