Skip to content

Commit d7b7b3f

Browse files
authored
Merge pull request #11 from Col-E/feature/lazy
Lazy reading in LocalFileHeader/CentralDirectoryFileHeader
2 parents 4fd3ee4 + 3f1d54f commit d7b7b3f

30 files changed

+1358
-665
lines changed

pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>software.coley</groupId>
88
<artifactId>lljzip</artifactId>
9-
<version>1.4.0</version>
9+
<version>1.5.0</version>
1010

1111
<name>LL Java ZIP</name>
1212
<description>Lower level ZIP support for Java</description>
@@ -95,6 +95,11 @@
9595
<target>1.8</target>
9696
</configuration>
9797
</plugin>
98+
<plugin>
99+
<groupId>org.apache.maven.plugins</groupId>
100+
<artifactId>maven-surefire-plugin</artifactId>
101+
<version>2.22.2</version>
102+
</plugin>
98103
</plugins>
99104
</build>
100105

src/main/java/software/coley/llzip/ZipIO.java

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package software.coley.llzip;
22

3+
import software.coley.llzip.format.model.CentralDirectoryFileHeader;
4+
import software.coley.llzip.format.model.EndOfCentralDirectory;
5+
import software.coley.llzip.format.model.ZipArchive;
36
import software.coley.llzip.format.read.ForwardScanZipReaderStrategy;
47
import software.coley.llzip.format.read.JvmZipReaderStrategy;
8+
import software.coley.llzip.format.read.NaiveLocalFileZipReaderStrategy;
59
import software.coley.llzip.format.read.ZipReaderStrategy;
6-
import software.coley.llzip.format.model.ZipArchive;
710
import software.coley.llzip.util.BufferData;
811
import software.coley.llzip.util.ByteData;
912
import software.coley.llzip.util.FileMapUtil;
@@ -15,6 +18,11 @@
1518

1619
/**
1720
* IO wrappers for reading {@link ZipArchive} contents.
21+
* <ul>
22+
* <li>For JAR files or anything intended to be read by the JVM use the JVM operations which use {@link JvmZipReaderStrategy}.</li>
23+
* <li>For regular ZIP files use {@link ForwardScanZipReaderStrategy}.</li>
24+
* <li>For ZIP files without {@link CentralDirectoryFileHeader} or {@link EndOfCentralDirectory} items, use {@link NaiveLocalFileZipReaderStrategy}</li>
25+
* </ul>
1826
*
1927
* @author Matt Coley
2028
*/
@@ -64,6 +72,51 @@ public static ZipArchive readStandard(Path data) throws IOException {
6472
return read(data, new ForwardScanZipReaderStrategy());
6573
}
6674

75+
/**
76+
* Creates an archive using the {@link NaiveLocalFileZipReaderStrategy}.
77+
*
78+
* @param data
79+
* Zip bytes.
80+
*
81+
* @return Archive from bytes.
82+
*
83+
* @throws IOException
84+
* When the archive bytes cannot be read from, usually indicating a malformed zip.
85+
*/
86+
public static ZipArchive readNaive(ByteData data) throws IOException {
87+
return read(data, new NaiveLocalFileZipReaderStrategy());
88+
}
89+
90+
/**
91+
* Creates an archive using the {@link NaiveLocalFileZipReaderStrategy}.
92+
*
93+
* @param data
94+
* Zip bytes.
95+
*
96+
* @return Archive from bytes.
97+
*
98+
* @throws IOException
99+
* When the archive bytes cannot be read from, usually indicating a malformed zip.
100+
*/
101+
public static ZipArchive readNaive(byte[] data) throws IOException {
102+
return read(data, new NaiveLocalFileZipReaderStrategy());
103+
}
104+
105+
/**
106+
* Creates an archive using the {@link NaiveLocalFileZipReaderStrategy}.
107+
*
108+
* @param data
109+
* Zip path.
110+
*
111+
* @return Archive from bytes.
112+
*
113+
* @throws IOException
114+
* When the archive bytes cannot be read from, usually indicating a malformed zip.
115+
*/
116+
public static ZipArchive readNaive(Path data) throws IOException {
117+
return read(data, new NaiveLocalFileZipReaderStrategy());
118+
}
119+
67120
/**
68121
* Creates an archive using the {@link JvmZipReaderStrategy} which handles some edge cases not usually
69122
* expected from zip files.
@@ -127,6 +180,7 @@ public static ZipArchive read(ByteData data, ZipReaderStrategy strategy) throws
127180
if (data == null)
128181
throw new IOException("Data is null!");
129182
// The fixed size elements of a CDFH is 22 bytes (plus the variable size bits which can be 0)
183+
// - Even if we only want to read local/central file entries, those are even larger at a minimum
130184
if (data.length() < 22)
131185
throw new IOException("Not enough bytes to read Central-Directory-File-Header, minimum=22");
132186
// Create instance

src/main/java/software/coley/llzip/format/ZipPatterns.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,32 @@ public interface ZipPatterns {
1515
* Any PK header match.
1616
*/
1717
int[] PK = {0x50, 0x4B};
18+
/**
19+
* Any PK header match, as a {@code u2/word/short}
20+
*/
21+
int PK_WORD = 0x4B_50;
1822
/**
1923
* Header for {@link LocalFileHeader}.
2024
*/
2125
int[] LOCAL_FILE_HEADER = {0x50, 0x4B, 0x03, 0x04};
26+
/**
27+
* Header for {@link LocalFileHeader}, as a {@code s4/quad/int}
28+
*/
29+
int LOCAL_FILE_HEADER_QUAD = 0x04_03_4B_50;
2230
/**
2331
* Header for {@link CentralDirectoryFileHeader}.
2432
*/
2533
int[] CENTRAL_DIRECTORY_FILE_HEADER = {0x50, 0x4B, 0x01, 0x02};
34+
/**
35+
* Header for {@link CentralDirectoryFileHeader}, as a {@code s4/quad/int}
36+
*/
37+
int CENTRAL_DIRECTORY_FILE_HEADER_QUAD = 0x02_01_4B_50;
2638
/**
2739
* Header for {@link EndOfCentralDirectory}.
2840
*/
2941
int[] END_OF_CENTRAL_DIRECTORY = {0x50, 0x4B, 0x05, 0x06};
42+
/**
43+
* Header for {@link EndOfCentralDirectory}, as a {@code s4/quad/int}
44+
*/
45+
int END_OF_CENTRAL_DIRECTORY_QUAD = 0x06_05_4B_50;
3046
}

src/main/java/software/coley/llzip/format/compression/DeflateDecompressor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*/
1818
public class DeflateDecompressor implements Decompressor {
1919
@Override
20-
public ByteData decompress(LocalFileHeader header, ByteData bytes) throws IOException {
20+
public ByteData decompress(LocalFileHeader header, ByteData data) throws IOException {
2121
if (header.getCompressionMethod() != ZipCompressions.DEFLATED)
2222
throw new IOException("LocalFileHeader contents not using 'Deflated'!");
2323
Inflater inflater = new Inflater(true);
@@ -26,14 +26,14 @@ public ByteData decompress(LocalFileHeader header, ByteData bytes) throws IOExce
2626
byte[] output = new byte[1024];
2727
byte[] buffer = new byte[1024];
2828
long position = 0L;
29-
long length = bytes.length();
29+
long length = data.length();
3030
do {
3131
if (inflater.needsInput()) {
3232
int remaining = (int) Math.min(buffer.length, length);
3333
if (remaining == 0) {
3434
break;
3535
}
36-
bytes.get(position, buffer, 0, remaining);
36+
data.get(position, buffer, 0, remaining);
3737
length -= remaining;
3838
position += remaining;
3939
inflater.setInput(buffer, 0, remaining);

0 commit comments

Comments
 (0)