/** * Writes bytes to ZIP entry. * * @param b the byte array to write * @param offset the start position to write from * @param length the number of bytes to write * @throws IOException on error */ @Override public void write(byte[] b, int offset, int length) throws IOException { if (entry == null) { throw new IllegalStateException("No current entry"); } ZipUtil.checkRequestedFeatures(entry.entry); entry.hasWritten = true; if (entry.entry.getMethod() == DEFLATED) { writeDeflated(b, offset, length); } else { writeOut(b, offset, length); written += length; } crc.update(b, offset, length); count(length); }
/** write implementation for DEFLATED entries. */ private void writeDeflated(byte[] b, int offset, int length) throws IOException { if (length > 0 && !def.finished()) { entry.bytesRead += length; if (length <= DEFLATER_BLOCK_SIZE) { def.setInput(b, offset, length); deflateUntilInputIsNeeded(); } else { final int fullblocks = length / DEFLATER_BLOCK_SIZE; for (int i = 0; i < fullblocks; i++) { def.setInput(b, offset + i * DEFLATER_BLOCK_SIZE, DEFLATER_BLOCK_SIZE); deflateUntilInputIsNeeded(); } final int done = fullblocks * DEFLATER_BLOCK_SIZE; if (done < length) { def.setInput(b, offset + done, length - done); deflateUntilInputIsNeeded(); } } } }
/** * Get the existing ZIP64 extended information extra field or create a new one and add it to the * entry. * * @since 1.3 */ private Zip64ExtendedInformationExtraField getZip64Extra(ZipArchiveEntry ze) { if (entry != null) { entry.causedUseOfZip64 = !hasUsedZip64; } hasUsedZip64 = true; Zip64ExtendedInformationExtraField z64 = (Zip64ExtendedInformationExtraField) ze.getExtraField(Zip64ExtendedInformationExtraField.HEADER_ID); if (z64 == null) { /* System.err.println("Adding z64 for " + ze.getName() + ", method: " + ze.getMethod() + " (" + (ze.getMethod() == STORED) + ")" + ", raf: " + (raf != null)); */ z64 = new Zip64ExtendedInformationExtraField(); } // even if the field is there already, make sure it is the first one ze.addAsFirstExtraField(z64); return z64; }
/** * Writes the local file header entry * * @param ze the entry to write * @throws IOException on error */ protected void writeLocalFileHeader(ZipArchiveEntry ze) throws IOException { boolean encodable = zipEncoding.canEncode(ze.getName()); ByteBuffer name = getName(ze); if (createUnicodeExtraFields != UnicodeExtraFieldPolicy.NEVER) { addUnicodeExtraFields(ze, encodable, name); } offsets.put(ze, Long.valueOf(written)); writeOut(LFH_SIG); written += WORD; // store method in local variable to prevent multiple method calls final int zipMethod = ze.getMethod(); writeVersionNeededToExtractAndGeneralPurposeBits( zipMethod, !encodable && fallbackToUTF8, hasZip64Extra(ze)); written += WORD; // compression method writeOut(ZipShort.getBytes(zipMethod)); written += SHORT; // last mod. time and date writeOut(ZipUtil.toDosTime(ze.getTime())); written += WORD; // CRC // compressed length // uncompressed length entry.localDataStart = written; if (zipMethod == DEFLATED || raf != null) { writeOut(LZERO); if (hasZip64Extra(entry.entry)) { // point to ZIP64 extended information extra field for // sizes, may get rewritten once sizes are known if // stream is seekable writeOut(ZipLong.ZIP64_MAGIC.getBytes()); writeOut(ZipLong.ZIP64_MAGIC.getBytes()); } else { writeOut(LZERO); writeOut(LZERO); } } else { writeOut(ZipLong.getBytes(ze.getCrc())); byte[] size = ZipLong.ZIP64_MAGIC.getBytes(); if (!hasZip64Extra(ze)) { size = ZipLong.getBytes(ze.getSize()); } writeOut(size); writeOut(size); } // CheckStyle:MagicNumber OFF written += 12; // CheckStyle:MagicNumber ON // file name length writeOut(ZipShort.getBytes(name.limit())); written += SHORT; // extra field length byte[] extra = ze.getLocalFileDataExtra(); writeOut(ZipShort.getBytes(extra.length)); written += SHORT; // file name writeOut(name.array(), name.arrayOffset(), name.limit() - name.position()); written += name.limit(); // extra field writeOut(extra); written += extra.length; entry.dataStart = written; }