mirror of
https://github.com/corda/corda.git
synced 2025-01-08 14:03:06 +00:00
add zipOutputStream and change DeflaterOutputStream
This commit is contained in:
parent
6970bb26ae
commit
54484bc2eb
@ -11,16 +11,16 @@
|
|||||||
package java.util.zip;
|
package java.util.zip;
|
||||||
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.FilterOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class DeflaterOutputStream extends OutputStream {
|
public class DeflaterOutputStream extends FilterOutputStream {
|
||||||
private final OutputStream out;
|
protected final Deflater deflater;
|
||||||
private final Deflater deflater;
|
protected final byte[] buffer;
|
||||||
private final byte[] buffer;
|
|
||||||
|
|
||||||
public DeflaterOutputStream(OutputStream out, Deflater deflater, int bufferSize)
|
public DeflaterOutputStream(OutputStream out, Deflater deflater, int bufferSize)
|
||||||
{
|
{
|
||||||
this.out = out;
|
super(out);
|
||||||
this.deflater = deflater;
|
this.deflater = deflater;
|
||||||
this.buffer = new byte[bufferSize];
|
this.buffer = new byte[bufferSize];
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
/* Copyright (c) 2008-2013, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
package java.util.zip;
|
package java.util.zip;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -8,7 +18,6 @@ import java.util.List;
|
|||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
import java.util.zip.DeflaterOutputStream;
|
import java.util.zip.DeflaterOutputStream;
|
||||||
import java.util.zip.Deflater;
|
import java.util.zip.Deflater;
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,7 +26,11 @@ import java.io.BufferedOutputStream;
|
|||||||
* All hardcoded defaults match the defaults for openJDK,
|
* All hardcoded defaults match the defaults for openJDK,
|
||||||
* including PKZip version, bit flags set, compression level, etc
|
* including PKZip version, bit flags set, compression level, etc
|
||||||
*
|
*
|
||||||
* @author ReadyTalk Summer 2013 Intern Team
|
* @author David Chau
|
||||||
|
* @author Aaron Davis
|
||||||
|
* @author Christopher Jordan
|
||||||
|
* @author Riley Moses
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class ZipOutputStream extends DeflaterOutputStream {
|
public class ZipOutputStream extends DeflaterOutputStream {
|
||||||
private static final int SIGNATURE = 0x04034b50;
|
private static final int SIGNATURE = 0x04034b50;
|
||||||
@ -29,29 +42,24 @@ public class ZipOutputStream extends DeflaterOutputStream {
|
|||||||
private static final int END_OF_CENTRAL_DIRECTORY_SIG = 0x06054b50;
|
private static final int END_OF_CENTRAL_DIRECTORY_SIG = 0x06054b50;
|
||||||
private static final int DEFAULT_LEVEL = 6;
|
private static final int DEFAULT_LEVEL = 6;
|
||||||
|
|
||||||
private final OutputStream out;
|
private static final int INPUT_BUFFER_SIZE = 1024;
|
||||||
private DeflaterOutputStream deflaterStream;
|
|
||||||
private Deflater deflater;
|
|
||||||
private List<ZipEntry> entries;
|
private List<ZipEntry> entries;
|
||||||
private CRC32 crc = new CRC32();
|
private CRC32 crc = new CRC32();
|
||||||
private ZipEntry currentEntry;
|
private ZipEntry currentEntry; // holder for current entry
|
||||||
|
private int bytesWritten; // a counter for total bytes written
|
||||||
|
private int sizeOfCentralDirectory; // a counter for central dir size
|
||||||
|
|
||||||
private int bytesWritten;
|
// these are used for the function write(int b) to provide a speed increase
|
||||||
private int sizeOfCentralDirectory;
|
private byte[] inputBuffer = new byte[INPUT_BUFFER_SIZE];
|
||||||
private byte[] buffer;
|
private int bufferIndex;
|
||||||
|
|
||||||
public ZipOutputStream(OutputStream outStream, int bufferSize) {
|
|
||||||
super(outStream);
|
public ZipOutputStream(OutputStream outStream) {
|
||||||
out = outStream;
|
super(outStream, new Deflater(DEFAULT_LEVEL, true));
|
||||||
bytesWritten = 0;
|
bytesWritten = 0;
|
||||||
sizeOfCentralDirectory = 0;
|
sizeOfCentralDirectory = 0;
|
||||||
entries = new ArrayList<ZipEntry>();
|
entries = new ArrayList<ZipEntry>();
|
||||||
buffer = new byte[bufferSize];
|
|
||||||
deflater = new Deflater(DEFAULT_LEVEL, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ZipOutputStream(OutputStream outStream) {
|
|
||||||
this(outStream, 4 * 1024);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putNextEntry(ZipEntry e) throws IOException {
|
public void putNextEntry(ZipEntry e) throws IOException {
|
||||||
@ -62,51 +70,24 @@ public class ZipOutputStream extends DeflaterOutputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void closeEntry() throws IOException {
|
public void closeEntry() throws IOException {
|
||||||
deflater.finish();
|
// write remainder of buffer if partially full
|
||||||
while (!deflater.finished()) {
|
if (bufferIndex != 0) {
|
||||||
deflate();
|
write(inputBuffer, 0, bufferIndex);
|
||||||
|
bufferIndex = 0;
|
||||||
}
|
}
|
||||||
deflater.dispose();
|
|
||||||
deflater.reset();
|
finish();
|
||||||
|
|
||||||
currentEntry.crc = (int) crc.getValue();
|
currentEntry.crc = (int) crc.getValue();
|
||||||
crc.reset();
|
crc.reset();
|
||||||
writeDataDescriptor(currentEntry);
|
writeDataDescriptor(currentEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeLocalHeader(ZipEntry e) throws IOException {
|
@Override
|
||||||
writeFourBytes(SIGNATURE); // local header signature
|
|
||||||
writeTwoBytes(VERSION); // version used
|
|
||||||
writeTwoBytes(BITFLAG); // flags
|
|
||||||
writeTwoBytes(METHOD); // compression method
|
|
||||||
writeTwoBytes(e.modTime); // last modified time
|
|
||||||
writeTwoBytes(e.modDate); // last modified date
|
|
||||||
writeFourBytes(0); // CRC is 0 for local header
|
|
||||||
|
|
||||||
// with default flag settings, the compressed and uncompressed size
|
|
||||||
// is written here as 0 and written correctly in the data descripter
|
|
||||||
writeFourBytes(0); // compressed size
|
|
||||||
writeFourBytes(0); // uncompressed size
|
|
||||||
writeTwoBytes(e.name.length()); // length of file name
|
|
||||||
|
|
||||||
// extra field length, in this implementation extra field in not used
|
|
||||||
writeTwoBytes(0);
|
|
||||||
|
|
||||||
// write file name, return the number of bytes written
|
|
||||||
int len = writeVariableByteLength(e.getName());
|
|
||||||
|
|
||||||
bytesWritten += 30 + len;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeDataDescriptor(ZipEntry currentEntry) throws IOException {
|
|
||||||
writeFourBytes(DATA_DESCRIPTER_HEADER); // data descripter header
|
|
||||||
writeFourBytes(currentEntry.crc); // crc value
|
|
||||||
writeFourBytes(currentEntry.compSize); // compressed size
|
|
||||||
writeFourBytes(currentEntry.uncompSize); // uncompressed size
|
|
||||||
bytesWritten += 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(byte[] b, int offset, int length) throws IOException {
|
public void write(byte[] b, int offset, int length) throws IOException {
|
||||||
|
if (offset < 0 || length < 0 || b.length - (offset + length) < 0)
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
|
||||||
currentEntry.uncompSize += length;
|
currentEntry.uncompSize += length;
|
||||||
crc.update(b, offset, length);
|
crc.update(b, offset, length);
|
||||||
currentEntry.crc = (int) crc.getValue();
|
currentEntry.crc = (int) crc.getValue();
|
||||||
@ -116,10 +97,14 @@ public class ZipOutputStream extends DeflaterOutputStream {
|
|||||||
deflate();
|
deflate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void write(int b) throws IOException {
|
public void write(int b) throws IOException {
|
||||||
byte[] buf = new byte[1];
|
inputBuffer[bufferIndex] = (byte)(b & 0xff);
|
||||||
buf[0] = (byte)(b & 0xff);
|
bufferIndex += 1;
|
||||||
write(buf, 0, 1);
|
if (bufferIndex == 1024) {
|
||||||
|
write(inputBuffer, 0, bufferIndex);
|
||||||
|
bufferIndex = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deflate() throws IOException {
|
private void deflate() throws IOException {
|
||||||
@ -127,72 +112,133 @@ public class ZipOutputStream extends DeflaterOutputStream {
|
|||||||
currentEntry.compSize += len;
|
currentEntry.compSize += len;
|
||||||
bytesWritten += len;
|
bytesWritten += len;
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
out.write(buffer, 0 , len);
|
out.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeLocalHeader(ZipEntry e) throws IOException {
|
||||||
|
byte[] tmpBuffer = new byte[30];
|
||||||
|
|
||||||
|
addFourBytes(SIGNATURE, 0, tmpBuffer); // local header signature
|
||||||
|
addTwoBytes(VERSION, 4, tmpBuffer); // version used
|
||||||
|
addTwoBytes(BITFLAG, 6, tmpBuffer); // flags
|
||||||
|
addTwoBytes(METHOD, 8, tmpBuffer); // compression method
|
||||||
|
addFourBytes(e.modTimeDate, 10, tmpBuffer); // last mod date and time
|
||||||
|
addFourBytes(0, 14, tmpBuffer); // CRC is 0 for local header
|
||||||
|
|
||||||
|
// with default flag settings (bit 3 set) the compressed and uncompressed size
|
||||||
|
// is written here as 0 and written correctly in the data descripter
|
||||||
|
addFourBytes(0, 18, tmpBuffer); // compressed size
|
||||||
|
addFourBytes(0, 22, tmpBuffer); // uncompressed size
|
||||||
|
addTwoBytes(e.name.length(), 26, tmpBuffer); // length of file name
|
||||||
|
|
||||||
|
// extra field length, in this implementation extra field in not used
|
||||||
|
addTwoBytes(0, 28, tmpBuffer);
|
||||||
|
|
||||||
|
out.write(tmpBuffer, 0, 30);
|
||||||
|
|
||||||
|
// write file name, return the number of bytes written
|
||||||
|
int len = writeUTF8(e.getName());
|
||||||
|
|
||||||
|
bytesWritten += 30 + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeDataDescriptor(ZipEntry currentEntry) throws IOException {
|
||||||
|
byte[] tmpBuffer = new byte[16];
|
||||||
|
|
||||||
|
addFourBytes(DATA_DESCRIPTER_HEADER, 0, tmpBuffer); // data descripter header
|
||||||
|
addFourBytes(currentEntry.crc, 4, tmpBuffer); // crc value
|
||||||
|
addFourBytes(currentEntry.compSize, 8, tmpBuffer); // compressed size
|
||||||
|
addFourBytes(currentEntry.uncompSize, 12, tmpBuffer);// uncompressed size
|
||||||
|
out.write(tmpBuffer, 0, 16);
|
||||||
|
bytesWritten += 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeCentralDirectoryHeader(ZipEntry e) throws IOException {
|
private void writeCentralDirectoryHeader(ZipEntry e) throws IOException {
|
||||||
writeFourBytes(CENTRAL_FILE_HEADER); // central directory header signature
|
byte[] tmpBuffer = new byte[46];
|
||||||
writeTwoBytes(VERSION); // version made by
|
|
||||||
writeTwoBytes(VERSION); // version needed
|
|
||||||
writeTwoBytes(BITFLAG); // flags
|
|
||||||
writeTwoBytes(METHOD); // compression method
|
|
||||||
|
|
||||||
writeTwoBytes(e.modTime); // last mod time
|
addFourBytes(CENTRAL_FILE_HEADER, 0, tmpBuffer); // central directory header signature
|
||||||
writeTwoBytes(e.modDate); // last mod date
|
addTwoBytes(VERSION, 4, tmpBuffer); // version made by
|
||||||
writeFourBytes(e.crc); // crc
|
addTwoBytes(VERSION, 6, tmpBuffer); // version needed
|
||||||
writeFourBytes(e.compSize); // compressed size
|
addTwoBytes(BITFLAG, 8, tmpBuffer); // flags
|
||||||
writeFourBytes(e.uncompSize); // uncompressed size
|
addTwoBytes(METHOD, 10, tmpBuffer); // compression method
|
||||||
|
|
||||||
writeTwoBytes(e.getName().length()); // file name length
|
addFourBytes(e.modTimeDate, 12, tmpBuffer); // last mod date and time
|
||||||
|
addFourBytes(e.crc, 16, tmpBuffer); // crc
|
||||||
|
addFourBytes(e.compSize, 20, tmpBuffer); // compressed size
|
||||||
|
addFourBytes(e.uncompSize, 24, tmpBuffer); // uncompressed size
|
||||||
|
|
||||||
|
addTwoBytes(e.getName().length(), 28, tmpBuffer); // file name length
|
||||||
|
|
||||||
// the following 5 fields are all 0 for a simple default compression
|
// the following 5 fields are all 0 for a simple default compression
|
||||||
writeTwoBytes(0); // extra field length (not used)
|
addTwoBytes(0, 30, tmpBuffer); // extra field length (not used)
|
||||||
writeTwoBytes(0); // comment length (not used)
|
addTwoBytes(0, 32, tmpBuffer); // comment length (not used)
|
||||||
writeTwoBytes(0); // disk number start
|
addTwoBytes(0, 34, tmpBuffer); // disk number start
|
||||||
writeTwoBytes(0); // internal file attribute
|
addTwoBytes(0, 36, tmpBuffer); // internal file attribute
|
||||||
writeFourBytes(0); // external file attribute
|
addFourBytes(0, 38, tmpBuffer); // external file attribute
|
||||||
|
|
||||||
writeFourBytes((int) e.offset); // relative offset of local header
|
addFourBytes((int) e.offset, 42, tmpBuffer); // relative offset of local header
|
||||||
|
|
||||||
int len = writeVariableByteLength(e.getName());
|
out.write(tmpBuffer, 0, 46);
|
||||||
|
|
||||||
|
int len = writeUTF8(e.getName());
|
||||||
|
|
||||||
bytesWritten += 46 + len;
|
bytesWritten += 46 + len;
|
||||||
sizeOfCentralDirectory += 46 + len;
|
sizeOfCentralDirectory += 46 + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeEndofCentralDirectory(int offset) throws IOException {
|
private void writeEndofCentralDirectory(int offset) throws IOException {
|
||||||
|
byte[] tmpBuffer = new byte[22];
|
||||||
|
|
||||||
short numEntries = (short) entries.size();
|
short numEntries = (short) entries.size();
|
||||||
writeFourBytes(END_OF_CENTRAL_DIRECTORY_SIG); // end of central directory signature
|
addFourBytes(END_OF_CENTRAL_DIRECTORY_SIG, 0, tmpBuffer); // end of central directory signature
|
||||||
writeTwoBytes(0); // disk number
|
addTwoBytes(0, 4, tmpBuffer); // disk number
|
||||||
writeTwoBytes(0); // disk number where central dir starts
|
addTwoBytes(0, 6, tmpBuffer); // disk number where central dir starts
|
||||||
writeTwoBytes(numEntries); // number of entries on this disk
|
addTwoBytes(numEntries, 8, tmpBuffer); // number of entries on this disk
|
||||||
writeTwoBytes(numEntries); // number of entries in central dir
|
addTwoBytes(numEntries, 10, tmpBuffer); // number of entries in central dir
|
||||||
writeFourBytes(sizeOfCentralDirectory); // length of central directory
|
addFourBytes(sizeOfCentralDirectory, 12, tmpBuffer); // length of central directory
|
||||||
writeFourBytes(offset); // offset of central directory
|
addFourBytes(offset, 16, tmpBuffer); // offset of central directory
|
||||||
writeTwoBytes(0); // length of added comments (not used)
|
addTwoBytes(0, 20, tmpBuffer); // length of added comments (not used)
|
||||||
|
out.write(tmpBuffer, 0, 22);
|
||||||
bytesWritten += 22;
|
bytesWritten += 22;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
int centralDirOffset = bytesWritten;
|
int centralDirOffset = bytesWritten;
|
||||||
for (ZipEntry e : entries)
|
for (ZipEntry e : entries)
|
||||||
writeCentralDirectoryHeader(e);
|
writeCentralDirectoryHeader(e);
|
||||||
writeEndofCentralDirectory(centralDirOffset);
|
writeEndofCentralDirectory(centralDirOffset);
|
||||||
|
deflater.dispose();
|
||||||
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeTwoBytes(int bytes) throws IOException {
|
@Override
|
||||||
out.write(bytes & 0xff);
|
public void flush() throws IOException {
|
||||||
out.write((bytes >> 8) & 0xff);
|
out.write(inputBuffer, 0, inputBuffer.length);
|
||||||
|
inputBuffer = new byte[INPUT_BUFFER_SIZE];
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeFourBytes(int bytes) throws IOException {
|
private void finish() throws IOException {
|
||||||
out.write(bytes & 0xff);
|
deflater.finish();
|
||||||
out.write((bytes >> 8) & 0xff);
|
while (!deflater.finished()) {
|
||||||
out.write((bytes >> 16) & 0xff);
|
deflate();
|
||||||
out.write((bytes >> 24) & 0xff);
|
}
|
||||||
|
deflater.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int writeVariableByteLength(String text) throws IOException {
|
private void addTwoBytes(int bytes, int offset, byte[] buffer) throws IOException {
|
||||||
|
buffer[offset] = (byte) (bytes & 0xff);
|
||||||
|
buffer[offset + 1] = (byte) ((bytes >> 8) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFourBytes(int bytes, int offset, byte[] buffer) throws IOException {
|
||||||
|
buffer[offset] = (byte) (bytes & 0xff);
|
||||||
|
buffer[offset + 1] = (byte) ((bytes >> 8) & 0xff);
|
||||||
|
buffer[offset + 2] = (byte) ((bytes >> 16) & 0xff);
|
||||||
|
buffer[offset + 3] = (byte) ((bytes >> 24) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int writeUTF8(String text) throws IOException {
|
||||||
byte[] bytes = text.getBytes("UTF-8");
|
byte[] bytes = text.getBytes("UTF-8");
|
||||||
out.write(bytes, 0, bytes.length);
|
out.write(bytes, 0, bytes.length);
|
||||||
return bytes.length;
|
return bytes.length;
|
||||||
|
Loading…
Reference in New Issue
Block a user