Skip to content

Commit b7cbbb8

Browse files
authored
Merge pull request #15 from NeRdTheNed/master
Add copy zip writer strategy
2 parents 7fa0081 + e52328d commit b7cbbb8

File tree

3 files changed

+95
-2
lines changed

3 files changed

+95
-2
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
target/
2-
.idea/
2+
.idea/
3+
4+
# macOS junk files
5+
.DS_Store

src/main/java/software/coley/llzip/format/model/JvmLocalFileHeader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public void read(ByteData data, long offset) {
4444
// Valid data range found, map back to (localOffset, range)
4545
fileData = readLongSlice(data,
4646
new LazyLong(() -> dataOffsetStart - offset),
47-
new LazyLong(() -> dataOffsetEnd - offset));
47+
new LazyLong(() -> dataOffsetEnd - dataOffsetStart));
4848
foundData = true;
4949
} else {
5050
// Keep data reference to attempt restoration with later when linking to the CEN.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package software.coley.llzip.format.write;
2+
3+
import software.coley.llzip.format.ZipPatterns;
4+
import software.coley.llzip.format.model.CentralDirectoryFileHeader;
5+
import software.coley.llzip.format.model.EndOfCentralDirectory;
6+
import software.coley.llzip.format.model.LocalFileHeader;
7+
import software.coley.llzip.format.model.ZipArchive;
8+
import software.coley.llzip.util.ByteDataUtil;
9+
10+
import java.io.IOException;
11+
import java.io.OutputStream;
12+
13+
/**
14+
* Manually copies the input zip file.
15+
* Data is written as-is, and no validation is performed.
16+
*
17+
* @author Ned Loynd
18+
*/
19+
public class CopyZipWriterStrategy implements ZipWriterStrategy {
20+
private static void writeShortLE(OutputStream os, int value) throws IOException {
21+
os.write(value & 0xFF);
22+
os.write((value >> 8) & 0xFF);
23+
}
24+
25+
private static void writeIntLE(OutputStream os, int value) throws IOException {
26+
os.write(value & 0xFF);
27+
os.write((value >> 8) & 0xFF);
28+
os.write((value >> 16) & 0xFF);
29+
os.write((value >> 24) & 0xFF);
30+
}
31+
32+
@Override
33+
public void write(ZipArchive archive, OutputStream os) throws IOException {
34+
// Write local file headers.
35+
for (final LocalFileHeader fileHeader : archive.getLocalFiles()) {
36+
writeIntLE(os, ZipPatterns.LOCAL_FILE_HEADER_QUAD);
37+
writeShortLE(os, fileHeader.getVersionNeededToExtract());
38+
writeShortLE(os, fileHeader.getGeneralPurposeBitFlag());
39+
writeShortLE(os, fileHeader.getCompressionMethod());
40+
writeShortLE(os, fileHeader.getLastModFileTime());
41+
writeShortLE(os, fileHeader.getLastModFileDate());
42+
writeIntLE(os, fileHeader.getCrc32());
43+
writeIntLE(os, (int) fileHeader.getCompressedSize());
44+
writeIntLE(os, (int) fileHeader.getUncompressedSize());
45+
writeShortLE(os, fileHeader.getFileNameLength());
46+
writeShortLE(os, fileHeader.getExtraFieldLength());
47+
os.write(ByteDataUtil.toByteArray(fileHeader.getFileName()));
48+
os.write(ByteDataUtil.toByteArray(fileHeader.getExtraField()));
49+
os.write(ByteDataUtil.toByteArray(fileHeader.getFileData()));
50+
}
51+
52+
// Write central directory file headers.
53+
for (final CentralDirectoryFileHeader directory : archive.getCentralDirectories()) {
54+
writeIntLE(os, ZipPatterns.CENTRAL_DIRECTORY_FILE_HEADER_QUAD);
55+
writeShortLE(os, directory.getVersionMadeBy());
56+
writeShortLE(os, directory.getVersionNeededToExtract());
57+
writeShortLE(os, directory.getGeneralPurposeBitFlag());
58+
writeShortLE(os, directory.getCompressionMethod());
59+
writeShortLE(os, directory.getLastModFileTime());
60+
writeShortLE(os, directory.getLastModFileDate());
61+
writeIntLE(os, directory.getCrc32());
62+
writeIntLE(os, (int) directory.getCompressedSize());
63+
writeIntLE(os, (int) directory.getUncompressedSize());
64+
writeShortLE(os, directory.getFileNameLength());
65+
writeShortLE(os, directory.getExtraFieldLength());
66+
writeShortLE(os, directory.getFileCommentLength());
67+
writeShortLE(os, directory.getDiskNumberStart());
68+
writeShortLE(os, directory.getInternalFileAttributes());
69+
writeIntLE(os, directory.getExternalFileAttributes());
70+
writeIntLE(os, (int) directory.getRelativeOffsetOfLocalHeader());
71+
os.write(ByteDataUtil.toByteArray(directory.getFileName()));
72+
os.write(ByteDataUtil.toByteArray(directory.getExtraField()));
73+
os.write(ByteDataUtil.toByteArray(directory.getFileComment()));
74+
}
75+
76+
// Write end of central directory record.
77+
final EndOfCentralDirectory end = archive.getEnd();
78+
if (end != null) {
79+
writeIntLE(os, ZipPatterns.END_OF_CENTRAL_DIRECTORY_QUAD);
80+
writeShortLE(os, end.getDiskNumber());
81+
writeShortLE(os, end.getCentralDirectoryStartDisk());
82+
writeShortLE(os, end.getCentralDirectoryStartOffset());
83+
writeShortLE(os, end.getNumEntries());
84+
writeIntLE(os, (int) end.getCentralDirectorySize());
85+
writeIntLE(os, (int) end.getCentralDirectoryOffset());
86+
writeShortLE(os, end.getZipCommentLength());
87+
os.write(ByteDataUtil.toByteArray(end.getZipComment()));
88+
}
89+
}
90+
}

0 commit comments

Comments
 (0)