1170 int n;
1171 while (size > 0 &&
1172 (n = (int)readFullyAt(buf, 0, buf.length, locoff)) != -1)
1173 {
1174 if (size < n)
1175 n = (int)size;
1176 os.write(buf, 0, n);
1177 size -= n;
1178 locoff += n;
1179 }
1180 return written;
1181 }
1182
1183 private long writeEntry(Entry e, OutputStream os, byte[] buf)
1184 throws IOException {
1185
1186 if (e.bytes == null && e.file == null) // dir, 0-length data
1187 return 0;
1188
1189 long written = 0;
1190 try (OutputStream os2 = e.method == METHOD_STORED ?
1191 new EntryOutputStreamCRC32(e, os) : new EntryOutputStreamDef(e, os)) {
1192 if (e.bytes != null) { // in-memory
1193 os2.write(e.bytes, 0, e.bytes.length);
1194 } else if (e.file != null) { // tmp file
1195 if (e.type == Entry.NEW || e.type == Entry.FILECH) {
1196 try (InputStream is = Files.newInputStream(e.file)) {
1197 is.transferTo(os2);
1198 }
1199 }
1200 Files.delete(e.file);
1201 tmppaths.remove(e.file);
1202 }
1203 }
1204 written += e.csize;
1205 if ((e.flag & FLAG_DATADESCR) != 0) {
1206 written += e.writeEXT(os);
1207 }
1208 return written;
1209 }
1210
1211 // sync the zip file system, if there is any udpate
1212 private void sync() throws IOException {
1213
1214 if (!hasUpdate)
1215 return;
1216 Path tmpFile = createTempFileInSameDirectoryAs(zfpath);
1217 try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(tmpFile, WRITE)))
1218 {
1219 ArrayList<Entry> elist = new ArrayList<>(inodes.size());
1220 long written = 0;
1221 byte[] buf = new byte[8192];
1222 Entry e = null;
1223
1310 }
1311
1312 // Returns an out stream for either
1313 // (1) writing the contents of a new entry, if the entry exits, or
1314 // (2) updating/replacing the contents of the specified existing entry.
1315 private OutputStream getOutputStream(Entry e) throws IOException {
1316
1317 if (e.mtime == -1)
1318 e.mtime = System.currentTimeMillis();
1319 if (e.method == -1)
1320 e.method = defaultMethod;
1321 // store size, compressed size, and crc-32 in datadescr
1322 e.flag = FLAG_DATADESCR;
1323 if (zc.isUTF8())
1324 e.flag |= FLAG_USE_UTF8;
1325 OutputStream os;
1326 if (useTempFile) {
1327 e.file = getTempPathForEntry(null);
1328 os = Files.newOutputStream(e.file, WRITE);
1329 } else {
1330 os = new ByteArrayOutputStream((e.size > 0)? (int)e.size : 8192);
1331 }
1332 return new EntryOutputStream(e, os);
1333 }
1334
1335 private class EntryOutputStream extends FilterOutputStream {
1336 private Entry e;
1337 private long written;
1338 private boolean isClosed;
1339
1340 EntryOutputStream(Entry e, OutputStream os) throws IOException {
1341 super(os);
1342 this.e = Objects.requireNonNull(e, "Zip entry is null");
1343 // this.written = 0;
1344 }
1345
1346 @Override
1347 public synchronized void write(int b) throws IOException {
1348 out.write(b);
1349 written += 1;
1350 }
1351
1352 @Override
1353 public synchronized void write(byte b[], int off, int len)
1354 throws IOException {
1355 out.write(b, off, len);
1356 written += len;
1357 }
1358
1359 @Override
1360 public synchronized void close() throws IOException {
1361 if (isClosed) {
1362 return;
1363 }
1364 isClosed = true;
1365 e.size = written;
1366 if (out instanceof ByteArrayOutputStream)
1367 e.bytes = ((ByteArrayOutputStream)out).toByteArray();
1368 super.close();
1369 update(e);
1370 }
1371 }
1372
1373 // Wrapper output stream class to write out a "stored" entry.
1374 // (1) this class does not close the underlying out stream when
1375 // being closed.
1376 // (2) no need to be "synchronized", only used by sync()
1377 private class EntryOutputStreamCRC32 extends FilterOutputStream {
1378 private Entry e;
1379 private CRC32 crc;
1380 private long written;
1381 private boolean isClosed;
1382
1383 EntryOutputStreamCRC32(Entry e, OutputStream os) throws IOException {
1384 super(os);
1385 this.e = Objects.requireNonNull(e, "Zip entry is null");
1386 this.crc = new CRC32();
1387 }
1388
|
1170 int n;
1171 while (size > 0 &&
1172 (n = (int)readFullyAt(buf, 0, buf.length, locoff)) != -1)
1173 {
1174 if (size < n)
1175 n = (int)size;
1176 os.write(buf, 0, n);
1177 size -= n;
1178 locoff += n;
1179 }
1180 return written;
1181 }
1182
1183 private long writeEntry(Entry e, OutputStream os, byte[] buf)
1184 throws IOException {
1185
1186 if (e.bytes == null && e.file == null) // dir, 0-length data
1187 return 0;
1188
1189 long written = 0;
1190 if (e.bytes != null && e.crc != 0) {
1191 // precompressed entry, write directly to output stream
1192 os.write(e.bytes, 0, e.bytes.length);
1193 } else {
1194 try (OutputStream os2 = e.method == METHOD_STORED ?
1195 new EntryOutputStreamCRC32(e, os) : new EntryOutputStreamDef(e, os)) {
1196 if (e.bytes != null) { // in-memory
1197 os2.write(e.bytes, 0, e.bytes.length);
1198 } else if (e.file != null) { // tmp file
1199 if (e.type == Entry.NEW || e.type == Entry.FILECH) {
1200 try (InputStream is = Files.newInputStream(e.file)) {
1201 is.transferTo(os2);
1202 }
1203 }
1204 Files.delete(e.file);
1205 tmppaths.remove(e.file);
1206 }
1207 }
1208 }
1209 written += e.csize;
1210 if ((e.flag & FLAG_DATADESCR) != 0) {
1211 written += e.writeEXT(os);
1212 }
1213 return written;
1214 }
1215
1216 // sync the zip file system, if there is any udpate
1217 private void sync() throws IOException {
1218
1219 if (!hasUpdate)
1220 return;
1221 Path tmpFile = createTempFileInSameDirectoryAs(zfpath);
1222 try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(tmpFile, WRITE)))
1223 {
1224 ArrayList<Entry> elist = new ArrayList<>(inodes.size());
1225 long written = 0;
1226 byte[] buf = new byte[8192];
1227 Entry e = null;
1228
1315 }
1316
1317 // Returns an out stream for either
1318 // (1) writing the contents of a new entry, if the entry exits, or
1319 // (2) updating/replacing the contents of the specified existing entry.
1320 private OutputStream getOutputStream(Entry e) throws IOException {
1321
1322 if (e.mtime == -1)
1323 e.mtime = System.currentTimeMillis();
1324 if (e.method == -1)
1325 e.method = defaultMethod;
1326 // store size, compressed size, and crc-32 in datadescr
1327 e.flag = FLAG_DATADESCR;
1328 if (zc.isUTF8())
1329 e.flag |= FLAG_USE_UTF8;
1330 OutputStream os;
1331 if (useTempFile) {
1332 e.file = getTempPathForEntry(null);
1333 os = Files.newOutputStream(e.file, WRITE);
1334 } else {
1335 if (defaultMethod == METHOD_DEFLATED) {
1336 return new DeflatingByteArrayEntryOutputStream(e,
1337 new ByteArrayOutputStream((e.size > 0)? (int)e.size : 8192));
1338 }
1339 os = new ByteArrayOutputStream((e.size > 0)? (int)e.size : 8192);
1340 }
1341 return new EntryOutputStream(e, os);
1342 }
1343
1344 private class EntryOutputStream extends FilterOutputStream {
1345 private Entry e;
1346 private long written;
1347 private boolean isClosed;
1348
1349 EntryOutputStream(Entry e, OutputStream os) throws IOException {
1350 super(os);
1351 this.e = Objects.requireNonNull(e, "Zip entry is null");
1352 // this.written = 0;
1353 }
1354
1355 @Override
1356 public synchronized void write(int b) throws IOException {
1357 out.write(b);
1358 written += 1;
1359 }
1360
1361 @Override
1362 public synchronized void write(byte b[], int off, int len)
1363 throws IOException {
1364 out.write(b, off, len);
1365 written += len;
1366 }
1367
1368 @Override
1369 public synchronized void close() throws IOException {
1370 if (isClosed) {
1371 return;
1372 }
1373 isClosed = true;
1374 e.size = written;
1375 if (out instanceof ByteArrayOutputStream)
1376 e.bytes = ((ByteArrayOutputStream)out).toByteArray();
1377 super.close();
1378 update(e);
1379 }
1380 }
1381
1382 // Output stream returned when writing "deflated" entries into memory,
1383 // to enable eager (possibly parallel) deflation and reduce memory required.
1384 private class DeflatingByteArrayEntryOutputStream extends DeflaterOutputStream {
1385 private Entry e;
1386 private CRC32 crc;
1387 private boolean isClosed;
1388
1389 DeflatingByteArrayEntryOutputStream(Entry e, ByteArrayOutputStream os) throws IOException {
1390 super(os, getDeflater());
1391 this.e = Objects.requireNonNull(e, "Zip entry is null");
1392 this.crc = new CRC32();
1393 }
1394
1395 @Override
1396 public synchronized void write(int b) throws IOException {
1397 super.write(b);
1398 crc.update(b);
1399 }
1400
1401 @Override
1402 public synchronized void write(byte b[], int off, int len)
1403 throws IOException {
1404 super.write(b, off, len);
1405 crc.update(b, off, len);
1406 }
1407
1408 @Override
1409 public synchronized void close() throws IOException {
1410 if (isClosed)
1411 return;
1412 isClosed = true;
1413 finish();
1414 e.size = def.getBytesRead();
1415 e.csize = def.getBytesWritten();
1416 e.bytes = ((ByteArrayOutputStream)out).toByteArray();
1417 e.crc = crc.getValue();
1418 releaseDeflater(def);
1419 update(e);
1420 }
1421 }
1422
1423 // Wrapper output stream class to write out a "stored" entry.
1424 // (1) this class does not close the underlying out stream when
1425 // being closed.
1426 // (2) no need to be "synchronized", only used by sync()
1427 private class EntryOutputStreamCRC32 extends FilterOutputStream {
1428 private Entry e;
1429 private CRC32 crc;
1430 private long written;
1431 private boolean isClosed;
1432
1433 EntryOutputStreamCRC32(Entry e, OutputStream os) throws IOException {
1434 super(os);
1435 this.e = Objects.requireNonNull(e, "Zip entry is null");
1436 this.crc = new CRC32();
1437 }
1438
|