75
79
public class ZipArchiveOutputStream extends ArchiveOutputStream {
77
81
static final int BUFFER_SIZE = 512;
82
private static final int LFH_SIG_OFFSET = 0;
83
private static final int LFH_VERSION_NEEDED_OFFSET = 4;
84
private static final int LFH_GPB_OFFSET = 6;
85
private static final int LFH_METHOD_OFFSET = 8;
86
private static final int LFH_TIME_OFFSET = 10;
87
private static final int LFH_CRC_OFFSET = 14;
88
private static final int LFH_COMPRESSED_SIZE_OFFSET = 18;
89
private static final int LFH_ORIGINAL_SIZE_OFFSET = 22;
90
private static final int LFH_FILENAME_LENGTH_OFFSET = 26;
91
private static final int LFH_EXTRA_LENGTH_OFFSET = 28;
92
private static final int LFH_FILENAME_OFFSET = 30;
93
private static final int CFH_SIG_OFFSET = 0;
94
private static final int CFH_VERSION_MADE_BY_OFFSET = 4;
95
private static final int CFH_VERSION_NEEDED_OFFSET = 6;
96
private static final int CFH_GPB_OFFSET = 8;
97
private static final int CFH_METHOD_OFFSET = 10;
98
private static final int CFH_TIME_OFFSET = 12;
99
private static final int CFH_CRC_OFFSET = 16;
100
private static final int CFH_COMPRESSED_SIZE_OFFSET = 20;
101
private static final int CFH_ORIGINAL_SIZE_OFFSET = 24;
102
private static final int CFH_FILENAME_LENGTH_OFFSET = 28;
103
private static final int CFH_EXTRA_LENGTH_OFFSET = 30;
104
private static final int CFH_COMMENT_LENGTH_OFFSET = 32;
105
private static final int CFH_DISK_NUMBER_OFFSET = 34;
106
private static final int CFH_INTERNAL_ATTRIBUTES_OFFSET = 36;
107
private static final int CFH_EXTERNAL_ATTRIBUTES_OFFSET = 38;
108
private static final int CFH_LFH_OFFSET = 42;
109
private static final int CFH_FILENAME_OFFSET = 46;
79
111
/** indicates if this archive is finished. protected for use in Jar implementation */
80
112
protected boolean finished = false;
410
447
throw new IOException("This archive contains unclosed entries.");
414
for (ZipArchiveEntry ze : entries) {
415
writeCentralFileHeader(ze);
417
cdLength = written - cdOffset;
450
cdOffset = streamCompressor.getTotalBytesWritten();
451
writeCentralDirectoryInChunks();
453
cdLength = streamCompressor.getTotalBytesWritten() - cdOffset;
418
454
writeZip64CentralDirectory();
419
455
writeCentralDirectoryEnd();
458
streamCompressor.close();
462
private void writeCentralDirectoryInChunks() throws IOException {
463
int NUM_PER_WRITE = 1000;
464
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(70 * NUM_PER_WRITE);
466
for (ZipArchiveEntry ze : entries) {
467
byteArrayOutputStream.write(createCentralFileHeader(ze));
468
if (++count > NUM_PER_WRITE){
469
writeCounted(byteArrayOutputStream.toByteArray());
470
byteArrayOutputStream.reset();
474
writeCounted(byteArrayOutputStream.toByteArray());
427
478
* Writes all necessary data for this entry.
428
479
* @throws IOException on error
434
485
public void closeArchiveEntry() throws IOException {
436
throw new IOException("Stream has already been finished");
440
throw new IOException("No current entry to close");
443
if (!entry.hasWritten) {
490
long bytesWritten = streamCompressor.getTotalBytesWritten() - entry.dataStart;
491
long realCrc = streamCompressor.getCrc32();
492
entry.bytesRead = streamCompressor.getBytesRead();
449
493
final Zip64Mode effectiveMode = getEffectiveZip64Mode(entry.entry);
450
long bytesWritten = written - entry.dataStart;
451
long realCrc = crc.getValue();
454
final boolean actuallyNeedsZip64 =
455
handleSizesAndCrc(bytesWritten, realCrc, effectiveMode);
494
final boolean actuallyNeedsZip64 = handleSizesAndCrc(bytesWritten, realCrc, effectiveMode);
495
closeEntry(actuallyNeedsZip64, false);
496
streamCompressor.reset();
500
* Writes all necessary data for this entry.
502
* @throws IOException on error
503
* @throws Zip64RequiredException if the entry's uncompressed or
504
* compressed size exceeds 4 GByte and {@link #setUseZip64}
505
* is {@link Zip64Mode#Never}.
506
* @param phased This entry is second phase of a 2-phase zip creation, size, compressed size and crc
507
* are known in ZipArchiveEntry
509
private void closeCopiedEntry(boolean phased) throws IOException {
511
entry.bytesRead = entry.entry.getSize();
512
Zip64Mode effectiveMode = getEffectiveZip64Mode(entry.entry);
513
boolean actuallyNeedsZip64 = checkIfNeedsZip64(effectiveMode);
514
closeEntry(actuallyNeedsZip64, phased);
517
private void closeEntry(boolean actuallyNeedsZip64, boolean phased) throws IOException {
518
if (!phased && raf != null) {
458
519
rewriteSizesAndCrc(actuallyNeedsZip64);
526
private void preClose() throws IOException {
528
throw new IOException("Stream has already been finished");
532
throw new IOException("No current entry to close");
535
if (!entry.hasWritten) {
541
* Adds an archive entry with a raw input stream.
543
* If crc, size and compressed size are supplied on the entry, these values will be used as-is.
544
* Zip64 status is re-established based on the settings in this stream, and the supplied value
547
* The entry is put and closed immediately.
549
* @param entry The archive entry to add
550
* @param rawStream The raw input stream of a different entry. May be compressed/encrypted.
551
* @throws IOException If copying fails
553
public void addRawArchiveEntry(ZipArchiveEntry entry, InputStream rawStream)
555
ZipArchiveEntry ae = new ZipArchiveEntry(entry);
556
if (hasZip64Extra(ae)) {
557
// Will be re-added as required. this may make the file generated with this method
558
// somewhat smaller than standard mode,
559
// since standard mode is unable to remove the zip 64 header.
560
ae.removeExtraField(Zip64ExtendedInformationExtraField.HEADER_ID);
562
boolean is2PhaseSource = ae.getCrc() != ZipArchiveEntry.CRC_UNKNOWN
563
&& ae.getSize() != ArchiveEntry.SIZE_UNKNOWN
564
&& ae.getCompressedSize() != ArchiveEntry.SIZE_UNKNOWN;
565
putArchiveEntry(ae, is2PhaseSource);
566
copyFromZipInputStream(rawStream);
567
closeCopiedEntry(is2PhaseSource);
466
571
* Ensures all bytes sent to the deflater are written to the stream.
468
573
private void flushDeflater() throws IOException {
469
574
if (entry.entry.getMethod() == DEFLATED) {
471
while (!def.finished()) {
575
streamCompressor.flushDeflater();
515
616
entry.entry.setCrc(crc);
518
final boolean actuallyNeedsZip64 = effectiveMode == Zip64Mode.Always
519
|| entry.entry.getSize() >= ZIP64_MAGIC
520
|| entry.entry.getCompressedSize() >= ZIP64_MAGIC;
619
return checkIfNeedsZip64(effectiveMode);
623
* Ensures the current entry's size and CRC information is set to
624
* the values just written, verifies it isn't too big in the
625
* Zip64Mode.Never case and returns whether the entry would
626
* require a Zip64 extra field.
628
private boolean checkIfNeedsZip64(Zip64Mode effectiveMode)
629
throws ZipException {
630
final boolean actuallyNeedsZip64 = isZip64Required(entry.entry, effectiveMode);
521
631
if (actuallyNeedsZip64 && effectiveMode == Zip64Mode.Never) {
522
throw new Zip64RequiredException(Zip64RequiredException
523
.getEntryTooBigMessage(entry.entry));
632
throw new Zip64RequiredException(Zip64RequiredException.getEntryTooBigMessage(entry.entry));
525
634
return actuallyNeedsZip64;
637
private boolean isZip64Required(ZipArchiveEntry entry1, Zip64Mode requestedMode) {
638
return requestedMode == Zip64Mode.Always || isTooLageForZip32(entry1);
641
private boolean isTooLageForZip32(ZipArchiveEntry zipArchiveEntry){
642
return zipArchiveEntry.getSize() >= ZIP64_MAGIC || zipArchiveEntry.getCompressedSize() >= ZIP64_MAGIC;
529
646
* When using random access output, write the local file header
530
647
* and potentiall the ZIP64 extra containing the correct CRC and
757
897
throw new IllegalStateException("No current entry");
759
899
ZipUtil.checkRequestedFeatures(entry.entry);
900
long writtenThisTime = streamCompressor.write(b, offset, length, entry.entry.getMethod());
901
count(writtenThisTime);
905
* Write bytes to output or random access file.
906
* @param data the byte array to write
907
* @throws IOException on error
909
private void writeCounted(byte[] data) throws IOException {
910
streamCompressor.writeCounted(data);
913
private void copyFromZipInputStream(InputStream src) throws IOException {
915
throw new IllegalStateException("No current entry");
917
ZipUtil.checkRequestedFeatures(entry.entry);
760
918
entry.hasWritten = true;
761
if (entry.entry.getMethod() == DEFLATED) {
762
writeDeflated(b, offset, length);
764
writeOut(b, offset, length);
767
crc.update(b, offset, length);
772
* write implementation for DEFLATED entries.
774
private void writeDeflated(byte[]b, int offset, int length)
776
if (length > 0 && !def.finished()) {
777
entry.bytesRead += length;
778
if (length <= DEFLATER_BLOCK_SIZE) {
779
def.setInput(b, offset, length);
780
deflateUntilInputIsNeeded();
782
final int fullblocks = length / DEFLATER_BLOCK_SIZE;
783
for (int i = 0; i < fullblocks; i++) {
784
def.setInput(b, offset + i * DEFLATER_BLOCK_SIZE,
785
DEFLATER_BLOCK_SIZE);
786
deflateUntilInputIsNeeded();
788
final int done = fullblocks * DEFLATER_BLOCK_SIZE;
790
def.setInput(b, offset + done, length - done);
791
deflateUntilInputIsNeeded();
920
while ((length = src.read(copyBuffer)) >= 0 )
922
streamCompressor.writeCounted(copyBuffer, 0, length);
878
1007
addUnicodeExtraFields(ze, encodable, name);
881
offsets.put(ze, Long.valueOf(written));
1010
final byte[] localHeader = createLocalFileHeader(ze, name, encodable, phased);
1011
long localHeaderStart = streamCompressor.getTotalBytesWritten();
1012
offsets.put(ze, localHeaderStart);
1013
entry.localDataStart = localHeaderStart + LFH_CRC_OFFSET; // At crc offset
1014
writeCounted(localHeader);
1015
entry.dataStart = streamCompressor.getTotalBytesWritten();
1019
private byte[] createLocalFileHeader(ZipArchiveEntry ze, ByteBuffer name, boolean encodable,
1021
byte[] extra = ze.getLocalFileDataExtra();
1022
final int nameLen = name.limit() - name.position();
1023
int len= LFH_FILENAME_OFFSET + nameLen + extra.length;
1024
byte[] buf = new byte[len];
1026
System.arraycopy(LFH_SIG, 0, buf, LFH_SIG_OFFSET, WORD);
886
1028
//store method in local variable to prevent multiple method calls
887
1029
final int zipMethod = ze.getMethod();
889
writeVersionNeededToExtractAndGeneralPurposeBits(zipMethod,
1031
if (phased && !isZip64Required(entry.entry, zip64Mode)){
1032
putShort(INITIAL_VERSION, buf, LFH_VERSION_NEEDED_OFFSET);
1034
putShort(versionNeededToExtract(zipMethod, hasZip64Extra(ze)), buf, LFH_VERSION_NEEDED_OFFSET);
1037
GeneralPurposeBit generalPurposeBit = getGeneralPurposeBits(zipMethod, !encodable && fallbackToUTF8);
1038
generalPurposeBit.encode(buf, LFH_GPB_OFFSET);
895
1040
// compression method
896
writeOut(ZipShort.getBytes(zipMethod));
1041
putShort(zipMethod, buf, LFH_METHOD_OFFSET);
899
// last mod. time and date
900
writeOut(ZipUtil.toDosTime(ze.getTime()));
1043
ZipUtil.toDosTime(calendarInstance, ze.getTime(), buf, LFH_TIME_OFFSET);
1047
putLong(ze.getCrc(), buf, LFH_CRC_OFFSET);
1048
} else if (zipMethod == DEFLATED || raf != null) {
1049
System.arraycopy(LZERO, 0, buf, LFH_CRC_OFFSET, WORD);
1051
putLong(ze.getCrc(), buf, LFH_CRC_OFFSET);
904
1054
// compressed length
905
1055
// uncompressed length
906
entry.localDataStart = written;
907
if (zipMethod == DEFLATED || raf != null) {
909
if (hasZip64Extra(entry.entry)) {
910
// point to ZIP64 extended information extra field for
911
// sizes, may get rewritten once sizes are known if
912
// stream is seekable
913
writeOut(ZipLong.ZIP64_MAGIC.getBytes());
914
writeOut(ZipLong.ZIP64_MAGIC.getBytes());
920
writeOut(ZipLong.getBytes(ze.getCrc()));
921
byte[] size = ZipLong.ZIP64_MAGIC.getBytes();
922
if (!hasZip64Extra(ze)) {
923
size = ZipLong.getBytes(ze.getSize());
1056
if (hasZip64Extra(entry.entry)){
1057
// point to ZIP64 extended information extra field for
1058
// sizes, may get rewritten once sizes are known if
1059
// stream is seekable
1060
ZipLong.ZIP64_MAGIC.putLong(buf, LFH_COMPRESSED_SIZE_OFFSET);
1061
ZipLong.ZIP64_MAGIC.putLong(buf, LFH_ORIGINAL_SIZE_OFFSET);
1062
} else if (phased) {
1063
putLong(ze.getCompressedSize(), buf, LFH_COMPRESSED_SIZE_OFFSET);
1064
putLong(ze.getSize(), buf, LFH_ORIGINAL_SIZE_OFFSET);
1065
} else if (zipMethod == DEFLATED || raf != null) {
1066
System.arraycopy(LZERO, 0, buf, LFH_COMPRESSED_SIZE_OFFSET, WORD);
1067
System.arraycopy(LZERO, 0, buf, LFH_ORIGINAL_SIZE_OFFSET, WORD);
1069
putLong(ze.getSize(), buf, LFH_COMPRESSED_SIZE_OFFSET);
1070
putLong(ze.getSize(), buf, LFH_ORIGINAL_SIZE_OFFSET);
928
// CheckStyle:MagicNumber OFF
930
// CheckStyle:MagicNumber ON
932
1072
// file name length
933
writeOut(ZipShort.getBytes(name.limit()));
1073
putShort(nameLen, buf, LFH_FILENAME_LENGTH_OFFSET);
936
1075
// extra field length
937
byte[] extra = ze.getLocalFileDataExtra();
938
writeOut(ZipShort.getBytes(extra.length));
1076
putShort(extra.length, buf, LFH_EXTRA_LENGTH_OFFSET);
942
writeOut(name.array(), name.arrayOffset(),
943
name.limit() - name.position());
944
written += name.limit();
948
written += extra.length;
950
entry.dataStart = written;
1079
System.arraycopy( name.array(), name.arrayOffset(), buf, LFH_FILENAME_OFFSET, nameLen);
1081
System.arraycopy(extra, 0, buf, LFH_FILENAME_OFFSET + nameLen, extra.length);
954
1087
* Adds UnicodeExtra fields for name and file comment if mode is
955
1088
* ALWAYS or the data cannot be encoded using the configured
1017
1147
* Zip64Mode#Never}.
1019
1149
protected void writeCentralFileHeader(ZipArchiveEntry ze) throws IOException {
1023
final long lfhOffset = offsets.get(ze).longValue();
1150
byte[] centralFileHeader = createCentralFileHeader(ze);
1151
writeCounted(centralFileHeader);
1154
private byte[] createCentralFileHeader(ZipArchiveEntry ze) throws IOException {
1156
final long lfhOffset = offsets.get(ze);
1024
1157
final boolean needsZip64Extra = hasZip64Extra(ze)
1025
|| ze.getCompressedSize() >= ZIP64_MAGIC
1026
|| ze.getSize() >= ZIP64_MAGIC
1027
|| lfhOffset >= ZIP64_MAGIC;
1158
|| ze.getCompressedSize() >= ZIP64_MAGIC
1159
|| ze.getSize() >= ZIP64_MAGIC
1160
|| lfhOffset >= ZIP64_MAGIC;
1029
1162
if (needsZip64Extra && zip64Mode == Zip64Mode.Never) {
1030
1163
// must be the offset that is too big, otherwise an
1031
1164
// exception would have been throw in putArchiveEntry or
1032
1165
// closeArchiveEntry
1033
1166
throw new Zip64RequiredException(Zip64RequiredException
1034
.ARCHIVE_TOO_BIG_MESSAGE);
1167
.ARCHIVE_TOO_BIG_MESSAGE);
1037
1171
handleZip64Extra(ze, lfhOffset, needsZip64Extra);
1040
// CheckStyle:MagicNumber OFF
1041
writeOut(ZipShort.getBytes((ze.getPlatform() << 8) |
1042
(!hasUsedZip64 ? DATA_DESCRIPTOR_MIN_VERSION
1043
: ZIP64_MIN_VERSION)));
1046
final int zipMethod = ze.getMethod();
1047
final boolean encodable = zipEncoding.canEncode(ze.getName());
1048
writeVersionNeededToExtractAndGeneralPurposeBits(zipMethod,
1054
// compression method
1055
writeOut(ZipShort.getBytes(zipMethod));
1058
// last mod. time and date
1059
writeOut(ZipUtil.toDosTime(ze.getTime()));
1063
// compressed length
1064
// uncompressed length
1065
writeOut(ZipLong.getBytes(ze.getCrc()));
1066
if (ze.getCompressedSize() >= ZIP64_MAGIC
1067
|| ze.getSize() >= ZIP64_MAGIC) {
1068
writeOut(ZipLong.ZIP64_MAGIC.getBytes());
1069
writeOut(ZipLong.ZIP64_MAGIC.getBytes());
1071
writeOut(ZipLong.getBytes(ze.getCompressedSize()));
1072
writeOut(ZipLong.getBytes(ze.getSize()));
1074
// CheckStyle:MagicNumber OFF
1076
// CheckStyle:MagicNumber ON
1078
ByteBuffer name = getName(ze);
1080
writeOut(ZipShort.getBytes(name.limit()));
1083
// extra field length
1173
return createCentralFileHeader(ze, getName(ze), lfhOffset, needsZip64Extra);
1177
* Writes the central file header entry.
1178
* @param ze the entry to write
1179
* @param name The encoded name
1180
* @param lfhOffset Local file header offset for this file
1181
* @throws IOException on error
1183
private byte[] createCentralFileHeader(ZipArchiveEntry ze, ByteBuffer name, long lfhOffset,
1184
boolean needsZip64Extra) throws IOException {
1084
1185
byte[] extra = ze.getCentralDirectoryExtra();
1085
writeOut(ZipShort.getBytes(extra.length));
1088
1187
// file comment length
1089
1188
String comm = ze.getComment();
1094
1193
ByteBuffer commentB = getEntryEncoding(ze).encode(comm);
1096
writeOut(ZipShort.getBytes(commentB.limit()));
1194
final int nameLen = name.limit() - name.position();
1195
final int commentLen = commentB.limit() - commentB.position();
1196
int len= CFH_FILENAME_OFFSET + nameLen + extra.length + commentLen;
1197
byte[] buf = new byte[len];
1199
System.arraycopy(CFH_SIG, 0, buf, CFH_SIG_OFFSET, WORD);
1202
// CheckStyle:MagicNumber OFF
1203
putShort((ze.getPlatform() << 8) | (!hasUsedZip64 ? DATA_DESCRIPTOR_MIN_VERSION : ZIP64_MIN_VERSION),
1204
buf, CFH_VERSION_MADE_BY_OFFSET);
1206
final int zipMethod = ze.getMethod();
1207
final boolean encodable = zipEncoding.canEncode(ze.getName());
1208
putShort(versionNeededToExtract(zipMethod, needsZip64Extra), buf, CFH_VERSION_NEEDED_OFFSET);
1209
getGeneralPurposeBits(zipMethod, !encodable && fallbackToUTF8).encode(buf, CFH_GPB_OFFSET);
1211
// compression method
1212
putShort(zipMethod, buf, CFH_METHOD_OFFSET);
1215
// last mod. time and date
1216
ZipUtil.toDosTime(calendarInstance, ze.getTime(), buf, CFH_TIME_OFFSET);
1219
// compressed length
1220
// uncompressed length
1221
putLong(ze.getCrc(), buf, CFH_CRC_OFFSET);
1222
if (ze.getCompressedSize() >= ZIP64_MAGIC
1223
|| ze.getSize() >= ZIP64_MAGIC) {
1224
ZipLong.ZIP64_MAGIC.putLong(buf, CFH_COMPRESSED_SIZE_OFFSET);
1225
ZipLong.ZIP64_MAGIC.putLong(buf, CFH_ORIGINAL_SIZE_OFFSET);
1227
putLong(ze.getCompressedSize(), buf, CFH_COMPRESSED_SIZE_OFFSET);
1228
putLong(ze.getSize(), buf, CFH_ORIGINAL_SIZE_OFFSET);
1231
putShort(nameLen, buf, CFH_FILENAME_LENGTH_OFFSET);
1233
// extra field length
1234
putShort(extra.length, buf, CFH_EXTRA_LENGTH_OFFSET);
1236
putShort(commentLen, buf, CFH_COMMENT_LENGTH_OFFSET);
1099
1238
// disk number start
1239
System.arraycopy(ZERO, 0, buf, CFH_DISK_NUMBER_OFFSET, SHORT);
1103
1241
// internal file attributes
1104
writeOut(ZipShort.getBytes(ze.getInternalAttributes()));
1242
putShort(ze.getInternalAttributes(), buf, CFH_INTERNAL_ATTRIBUTES_OFFSET);
1107
1244
// external file attributes
1108
writeOut(ZipLong.getBytes(ze.getExternalAttributes()));
1245
putLong(ze.getExternalAttributes(), buf, CFH_EXTERNAL_ATTRIBUTES_OFFSET);
1111
1247
// relative offset of LFH
1112
writeOut(ZipLong.getBytes(Math.min(lfhOffset, ZIP64_MAGIC)));
1248
putLong(Math.min(lfhOffset, ZIP64_MAGIC), buf, CFH_LFH_OFFSET);
1116
writeOut(name.array(), name.arrayOffset(),
1117
name.limit() - name.position());
1118
written += name.limit();
1122
written += extra.length;
1251
System.arraycopy(name.array(), name.arrayOffset(), buf, CFH_FILENAME_OFFSET, nameLen);
1253
int extraStart = CFH_FILENAME_OFFSET + nameLen;
1254
System.arraycopy(extra, 0, buf, extraStart, extra.length);
1256
int commentStart = extraStart + extra.length;
1124
1258
// file comment
1125
writeOut(commentB.array(), commentB.arrayOffset(),
1126
commentB.limit() - commentB.position());
1127
written += commentB.limit();
1259
System.arraycopy(commentB.array(), commentB.arrayOffset(), buf, commentStart, commentLen);
1180
1313
byte[] num = ZipShort.getBytes(Math.min(numberOfEntries,
1181
1314
ZIP64_MAGIC_SHORT));
1185
1318
// length and location of CD
1186
writeOut(ZipLong.getBytes(Math.min(cdLength, ZIP64_MAGIC)));
1187
writeOut(ZipLong.getBytes(Math.min(cdOffset, ZIP64_MAGIC)));
1319
writeCounted(ZipLong.getBytes(Math.min(cdLength, ZIP64_MAGIC)));
1320
writeCounted(ZipLong.getBytes(Math.min(cdOffset, ZIP64_MAGIC)));
1189
1322
// ZIP file comment
1190
1323
ByteBuffer data = this.zipEncoding.encode(comment);
1191
writeOut(ZipShort.getBytes(data.limit()));
1192
writeOut(data.array(), data.arrayOffset(),
1193
data.limit() - data.position());
1324
int dataLen = data.limit() - data.position();
1325
writeCounted(ZipShort.getBytes(dataLen));
1326
streamCompressor.writeCounted(data.array(), data.arrayOffset(), dataLen);
1196
private static final byte[] ONE = ZipLong.getBytes(1L);
1199
1330
* Writes the "ZIP64 End of central dir record" and
1200
1331
* "ZIP64 End of central dir locator".
1280
1412
* @throws IOException on error
1282
1414
protected final void writeOut(byte[] data, int offset, int length)
1283
throws IOException {
1285
raf.write(data, offset, length);
1287
out.write(data, offset, length);
1291
private void deflateUntilInputIsNeeded() throws IOException {
1292
while (!def.needsInput()) {
1297
private void writeVersionNeededToExtractAndGeneralPurposeBits(final int
1303
throws IOException {
1305
// CheckStyle:MagicNumber OFF
1306
int versionNeededToExtract = INITIAL_VERSION;
1415
throws IOException {
1416
streamCompressor.writeOut(data, offset, length);
1420
private GeneralPurposeBit getGeneralPurposeBits(final int zipMethod, final boolean utfFallback) {
1307
1421
GeneralPurposeBit b = new GeneralPurposeBit();
1308
1422
b.useUTF8ForNames(useUTF8Flag || utfFallback);
1309
if (zipMethod == DEFLATED && raf == null) {
1310
// requires version 2 as we are going to store length info
1311
// in the data descriptor
1312
versionNeededToExtract = DATA_DESCRIPTOR_MIN_VERSION;
1423
if (isDeflatedToOutputStream(zipMethod)) {
1313
1424
b.useDataDescriptor(true);
1429
private int versionNeededToExtract(final int zipMethod, final boolean zip64) {
1316
versionNeededToExtract = ZIP64_MIN_VERSION;
1431
return ZIP64_MIN_VERSION;
1318
// CheckStyle:MagicNumber ON
1320
// version needed to extract
1321
writeOut(ZipShort.getBytes(versionNeededToExtract));
1322
// general purpose bit flag
1323
writeOut(b.encode());
1433
// requires version 2 as we are going to store length info
1434
// in the data descriptor
1435
return (isDeflatedToOutputStream(zipMethod)) ?
1436
DATA_DESCRIPTOR_MIN_VERSION :
1440
private boolean isDeflatedToOutputStream(int zipMethod) {
1441
return zipMethod == DEFLATED && raf == null;
1327
1446
* Creates a new zip entry taking some information from the given